VSCode 写 Spring Boot,这个组合搁两三年前我说出来都不太有人信,编辑器怎么能干 IDE 的活。但这两年我实际用它做了几个完整的后端项目,从环境搭建到日常开发,除了个别大工程场景,基本没有需要切回 IDEA 的时候。这篇文章就把这套方案怎么落地完整写一遍:VSCode 里开发 Spring Boot 程序需要装哪些东西、项目怎么建、代码怎么写、问题怎么排,把我实际踩过的坑和现在还在用的配置都翻出来,给想折腾这个组合的同学一个参考。
1. 为什么用 VSCode 写 Spring Boot
1.1 这个组合适合谁
先说结论:不是所有人都适合用 VSCode 写 Spring Boot,但这套组合的适用人群比想象中广。我自己接触到的典型用户大概这么几类:
机器配置一般的开发者。IDEA 旗舰版开一个中型 Spring Boot 项目,内存占用时不时飙到 2GB 以上,老笔记本风扇狂转。VSCode 加上 Java 插件全家桶,日常用下来内存能控制在 800MB 到 1.2GB 左右,不算特别轻,但至少不会卡到影响打字。
以 Spring Boot 为辅助技能的前端或全栈开发者。很多人主业是 Vue、React,后端只是偶尔写几个接口给前端调,用 IDEA 属于杀鸡用牛刀,切换成本还高。VSCode 里前后端一套编辑器搞定,Git 操作、终端、代码片段都是同一套习惯,省了很多适应成本。
学生或者刚入门 Spring Boot 的朋友。IDEA 社区版免费但缺 Spring 相关支持,旗舰版又得走授权。VSCode 完全免费,装好插件就能体验自动补全、调试、一键运行,对学习阶段完全够用。
相反,如果是纯后端方向、每天面对十几个模块的大型多模块项目,或者重度依赖 IDEA 的 Refactor 和 Spring 专属检查,那 VSCode 确实差点意思,这部分在 1.2 会展开说。
1.2 与 IDEA 的对比:VSCode 的取舍
做技术选型最忌讳只看优点,把两边的短板摊开来看反而容易做决定。我大概列一下实际使用中的体感差异:
| 对比项 | VSCode + Java 插件 | IntelliJ IDEA(旗舰版) |
|---|---|---|
| 启动速度 | 快,打开即用 | 慢,加载时间明显 |
| 内存占用 | 低,日常开发约 1GB 左右 | 高,多模块项目轻松突破 2GB |
| 自动补全 | Java 基础补全够用,但复杂泛型推导偏弱 | 强,类型推理、链式调用体验好很多 |
| 重构能力 | 只有基础 Rename、提取变量,复杂重构会失灵 | 全量重构功能,批量改动很稳 |
| Spring 专属支持 | 有 Bean 跳转、配置提示,但不深 | 深度集成,AutoWired 检查、Bean 依赖图、Endpoints 窗口 |
| 插件生态 | 极丰富,且 Java 插件全家桶由微软官方维护 | 也有丰富插件,但很多好用功能得付费版才有 |
| 调试体验 | 可用,支持断点、变量查看、热部署 | 全面且稳定,多线程调试表现更好 |
一句话概括:VSCode 是“80% 的功能覆盖 90% 的日常需求”,IDEA 是“100% 的功能但代价是重”。我自己在写单模块项目、接口联调、微服务边角开发时用 VSCode,遇到大范围重构和深度排查才会开 IDEA。
这里还要解释一个很多人容易误解的点:VSCode 本身只是个编辑器,它之所以能写 Java,靠的是 Language Server Protocol(LSP)和 Debug Adapter Protocol(DAP)这套标准化协议。微软和 Eclipse 社区合作,把 Eclipse 的 JDT 编译器能力打包成语言服务器,再通过插件接进 VSCode。所以你在 VSCode 里写 Java 用的底层解析引擎其实是 Eclipse 的,不是 VSCode 自己实现的。这也是为什么某些极深的泛型推导或注解处理机制下,VSCode 的提示偶尔不如 IDEA 聪明。
1.3 配套技术栈的选择
开发 Spring Boot 项目,除了编辑器本身,构建工具和数据访问方案通常是最影响日常体验的两个选择。
构建工具一般就是 Maven 和 Gradle 二选一。Spring Boot 官方生成器和各种脚手架默认产出 Maven 项目,pom.xml 对新手最友好,依赖版本继承和传递依赖管理都是现成的。Gradle 的优势在构建速度和更灵活的脚本编写,适合复杂多模块项目,但 Gradle 版本和 Spring Boot 插件版本之间的兼容矩阵比较多,遇到问题排查起来比 Maven 费劲。在 VSCode 里这两个工具的体验差距不大——只要装了 Extension Pack for Java,编辑器会自动识别 pom.xml 和 build.gradle,依赖树、任务列表都能在侧边栏看到。
数据访问层是另一个选择点。Spring Boot 生态里最常见的是 Spring Data JPA 和 MyBatis 两派。JPA 的 Repository 接口写法简洁,单表 CRUD 几乎不用写 SQL,自带方法名解析,适合业务相对标准化的项目;MyBatis 则在 SQL 需要精细调优、存储过程、多表关联复杂的场景更顺手。在 VSCode 里这两者都能正常工作,但注意 MyBatis 需要额外装 MyBatisX 之类的插件才能获得 XML 映射文件和 Mapper 接口之间的跳转功能,JPA 则靠 Java Language Server 自带的符号跳转就够用。
2. 环境准备:装好这些才能开干
2.1 JDK 和构建工具怎么选
环境整个配下来最容易出问题的地方不是 VSCode,而是 JDK。Spring Boot 2.x 要求 JDK 8 以上,3.x 则必须 JDK 17 以上,热搜里经常出现的“springboot版本太高”问题,八成就是 JDK 和 Boot 版本对不上。
我在多台机器上配过这套环境,建议按这个顺序操作:
- 装 JDK。Windows 上我习惯用 Adoptium 的 OpenJDK 发行版,安装包干净、无广告、LTS 版本齐全。macOS 可以直接用 Homebrew 执行 brew install openjdk@17 这种命令装到指定版本。
- 配置 JAVA_HOME。Windows 在“系统环境变量”里新增 JAVA_HOME 指向 JDK 安装目录,再把 %JAVA_HOME%\bin 加到 Path。macOS/Linux 则写在 ~/.zshrc 或 ~/.bashrc 里。这一步漏了,VSCode 里的 Java 插件会提示找不到 JDK。
- 确认版本。在终端执行 java -version,如果本地装了多个 JDK,可以用命令切换好再往下走。
这里有个细节很多人踩过:VSCode 的 Java 插件首次启动时会按自己的逻辑去找 JDK,有时候它不读系统环境变量,而是读 settings.json 里的 java.configuration.runtimes 配置。如果你已经配置了环境变量但 VSCode 还是报错找不到 JDK,直接打开 VSCode 设置,搜 java.configuration.runtimes,填上 JDK 路径,马上就好。
Maven 或 Gradle 二选一的话,新手建议从 Maven 开始。Spring Boot 的官方文档、绝大多数博客教程、毕业设计里的部署流程,全部围绕 Maven 写的,遇到问题搜解决方案最方便。Maven 不需要单独安装也行——VSCode 的 Java 插件内置了 Maven 支持,首次打开 pom.xml 时会自动下载 Maven Core 并加载依赖。如果你想用自己装的 Maven,记得把 mvn 加到 Path 里,并在 VSCode 设置中指定 maven.executable.path。
2.2 必装插件清单
VSCode 插件市场里搜 Java 能看到结果一大堆,真正必要的不多。我这里给一份实际用下来能覆盖开发全流程的清单,有需要再按场景补充:
| 插件名称 | 作用 | 必装建议 |
|---|---|---|
| Extension Pack for Java | 微软官方全家桶,内含语言服务器、调试器、Maven 工具、测试运行器 | 必装 |
| Spring Boot Extension Pack | 含 Spring Initializr、Spring Boot Dashboard、Spring 配置提示 | 必装 |
| Lombok Annotations Support | 解决 Lombok 注解的编译和补全问题 | 用了 Lombok 必装 |
| Language Pack for Chinese | 界面汉化 | 按个人习惯 |
| Git 相关插件(GitLens) | 增强 Git 操作体验 | 推荐 |
Extension Pack for Java 装完就等于把 Java 语言服务器、Debugger for Java、Test Runner for Java、Maven for Java 这些一次性装齐了,不用单独一个个配。Spring Boot Extension Pack 里最实用的是 Dashboard,项目启动后会在侧边栏显示运行状态,点一下就能重启、停止、查看日志,比每次去终端敲命令舒服得多。
Lombok 这个插件经常被忽略,但只要你项目里用到 @Data、@Slf4j 这类注解,不装它 VSCode 就把这些字段和方法标成红色错误。注意顺序:先装 Extension Pack for Java,再装 Lombok 插件,装完 VSCode 会自动重启语言服务器重新编译工程。
2.3 VSCode 是怎么“读懂”Java 的
配置环境的时候顺便把这个原理搞清楚,后面排查问题会省很多时间。VSCode 对 Java 的支持主要由三个组件配合完成:
语言服务器(Eclipse JDT Language Server)。负责代码补全、符号跳转、错误标记、重构建议。它会在首次打开 Java 项目时启动,并读取 .classpath 和 pom.xml/build.gradle 来建立项目模型。几个 Java 文件组成的散工程和完整 Maven 工程的加载速度完全不一样,原因就在这里——依赖越多,语言服务器构建索引的时间越长。
调试适配器(Debugger for Java)。实现 DAP 协议,把 VSCode 的调试界面翻译成 JVM 能理解的调试指令,断点、栈帧、变量查看都走这一层。
构建工具集成(Maven for Java / Gradle for Java)。解析构建脚本,输出依赖树、插件任务列表,并在后台执行编译。VSCode 里右键 Run Java 或 Debug Java,本质上就是调用 Maven 的 compile 和 exec 任务。
理解这个结构后你就能明白:VSCode 对 Java 的支持不是“套壳”,而是真的把编译、补全、调试这些能力通过协议对接起来。不过协议对接毕竟多了一层转换,某些极端情况下会有延迟。比如我刚打开一个没有编译过的老项目,第一次按键触发补全可能会卡一两秒,等语言服务器构建完类路径索引之后就流畅了。
3. 从零搭一个 Spring Boot 项目
3.1 三种创建方式,按需选
VSCode 里创建 Spring Boot 项目,我试过三种方式,各自有适用场景。
第一种是用 Spring Initializr 插件。按 Ctrl+Shift+P 打开命令面板,输入 Spring Initializr,选择创建项目,接下来会依次问 Spring Boot 版本、语言、GroupId、ArtifactId、依赖。选完直接在 VSCode 里生成并解压项目。这种方式最直观,适合推荐给新手。注意这里选版本时不要无脑选 Latest Release,要看本机 JDK 版本。Spring Boot 3.2.x 要求 JDK 17 以上,如果你装的是 JDK 8 或 11,老老实实选 2.7.x 系列。
第二种是去 start.spring.io 网页生成项目压缩包,下载后解压再用 VSCode 打开。这种方式最稳定,因为网页端的初始化器维护最及时,依赖选择界面也更友好。遇到插件端 Initializr 服务连不上的情况,就用网页版生成。
第三种是纯手写。直接用 VSCode 创建文件夹,手写 pom.xml、启动类、配置文件。这种方式对初学者不友好,但对老手来说反而自由。我维护一个内部工具项目时就是这么干的,因为不想引入额外的 Spring Web 依赖,只想保留纯 Spring Boot 核心,手工写 pom 反而比向导更可控。
不管用哪种方式创建,成功后你会得到一个标准结构的工程目录。VSCode 首次打开时会提示是否信任文件夹,需要选择信任,否则语言服务器不会正常工作,这是一个经常被忽略的操作点。
3.2 项目结构拆解
一个标准的 Spring Boot 项目长这样:
demo ├── src │ ├── main │ │ ├── java │ │ │ └── com/example/demo │ │ │ ├── DemoApplication.java // 启动类 │ │ │ ├── controller/ // 控制器层 │ │ │ ├── service/ // 业务层 │ │ │ ├── repository/ // 数据访问层 │ │ │ ├── entity/ // 实体类 │ │ │ └── config/ // 配置类 │ │ └── resources │ │ ├── application.yml // 主配置文件 │ │ └── static/ // 静态资源 │ └── test │ └── java/... // 测试代码 ├── pom.xml └── README.md在 VSCode 里,这个目录结构会被语言服务器自动识别。你在 src/main/java 下新建类时,可以右键选择“在项目中创建新 Java 类”,插件会自动生成带包名的文件,不用手动维护目录层级。
很多教程会忽略一个细节:包路径和目录路径必须一致。Spring Boot 启动类上的 @SpringBootApplication 注解默认扫描范围是它所在包及其子包。也就是说如果启动类在 com.example.demo 下,Controller 放在 com.example.demo.controller 下就能被扫到;但如果你把 Controller 放到了 com.example.controller,启动后请求接口必然 404,而且编译器不会报错,排查起来特别隐蔽。
3.3 启动类的注意事项
启动类本身只有几行代码,但它是最容易被误解的文件:
package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }@SpringBootApplication 是个组合注解,等于 @Configuration + @EnableAutoConfiguration + @ComponentScan 三个注解拼在一起。所以它不仅能作为启动入口,还承担着组件扫描和自动配置的职责。
一个我经常提醒别人的坑:不要在启动类里写业务逻辑,也不要注解其他组件类。有些人在启动类上加了 @MapperScan 又同时在启动类里 Bean 上做自定义初始化,导致上下文加载顺序变得不可控。最佳实践是启动类保持干净,只负责启动;配置类单独拆到 config 包下,用 @Configuration 标注。
在 VSCode 里运行这个类也很简单:编辑器右上角会直接出现 Run 和 Debug 的灰按钮(Java 插件识别出 main 方法后会自动加),或者用 Spring Boot Dashboard 侧边栏里的按钮启动服务。启动成功后在终端看到 Tomcat started on port(s): 8080 就算通了。
4. 实操:写一个带数据访问的接口
4.1 application.yml 配置
配置文件是 Spring Boot 项目的核心,我习惯用 application.yml 而不是 properties 格式,因为缩进结构对应关系更清楚,注释层级也更自然。
一个最基础的配置大概长这样:
server: port: 8080 servlet: context-path: /api spring: application: name: demo-service datasource: url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: update show-sql: true写配置的时候可以利用 VSCode 的 Spring 配置提示功能:在 yml 文件里写 spring、server 这些关键词时,Spring Boot 插件会给出可用的配置路径和说明。这个功能是基于 Spring Configuration Processor 生成的 metadata 实现的,前提是项目里的 spring-boot-configuration-processor 依赖已经引入。
关于 ddl-auto 这个参数值得多说一句。update 模式可以自动建表或更新表结构,开发环境非常方便,但生产环境千万不要用。它不会删除列,但可能会因为隐式更新导致线上表结构和代码不一致。实际项目中我一般开发用 update,生产切到 validate 或者完全用 Flyway 这种迁移工具管理。
端口和 context-path 是日常改动最频繁的。context-path 设置后,所有接口都会自动带上 /api 前缀,比如原来的 localhost:8080/user 变成 localhost:8080/api/user。这在前端联调时经常用到,因为一般网关或 Nginx 转发会统一处理前缀。
4.2 数据访问层写法
Spring Data JPA 是数据访问层最省事的方案。先定义一个实体类:
package com.example.demo.entity; import jakarta.persistence.*; @Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false, unique = true) private String username; @Column(nullable = false) private String password; private String nickname; // getter / setter 省略 }这里特别要注意的是 2.x 和 3.x 的包名差异。Spring Boot 2.x 还用 javax.persistence 包,3.x 之后全面迁移到 jakarta.persistence。网上很多老教程贴的是 javax 版本,如果你用 3.x 直接复制会编译报错。我在 VSCode 里写代码时最常按的快捷键是 Ctrl+Shift+P 然后选“Java: 清理 Java 语言服务器工作区”,遇到包名变化导致的诡异编译错误,这个操作基本都能重置状态。
Repository 接口是这个样子:
package com.example.demo.repository; import com.example.demo.entity.User; import org.springframework.data.jpa.repository.JpaRepository; import java.util.Optional; public interface UserRepository extends JpaRepository<User, Long> { Optional<User> findByUsername(String username); boolean existsByUsername(String username); }这个方法名解析是 JPA 的魔法之一。Spring Data 会解析方法名,把 findByUsername 自动翻译成 where username = ? 的查询。VSCode 里的语言服务器对方法名解析的提示可能不如 IDEA 那么全,但基础的实体字段跳转和错误标注是没问题的。
4.3 Controller 与登录态处理
写一个最基础的 REST 接口:
package com.example.demo.controller; import com.example.demo.entity.User; import com.example.demo.repository.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/user") public class UserController { @Autowired private UserRepository userRepository; @GetMapping("/list") public List<User> list() { return userRepository.findAll(); } @PostMapping("/register") public User register(@RequestBody User user) { return userRepository.save(user); } }这个 Controller 里有个常被吐槽的点:直接在 Controller 里操作 Repository,严格来说不符合三层架构,但小项目这么写也完全能跑。我个人的建议是:当 service 层只是透传时,别强行加一层空壳,先跑通再重构,比一步到位更实际。
关于热词里频繁出现的“多个 springboot 项目如何一次登录其他不用登录”,实际项目里这个需求通常通过两种方案解决:一种是基于 Token 的认证(如 JWT),服务端不存 Session,多个服务共享同一个密钥校验 Token,那么只要登录一次,Token 在有效期内访问其他服务都能通过校验;另一种是统一认证中心(SSO),登录请求统一打到认证服务,回调之后各业务服务共享信任。这个设计在单体转微服务的阶段几乎一定会遇到。在 VSCode 里调试这种场景时我习惯用 REST Client 插件,写完 HTTP 请求保存成 .http 文件,直接点发送按钮就能看到响应。
需要注意的一个安全细节:上面例子里的 register 接口直接接收整个 User 对象,这在生产环境是有风险的。前端可以传一个 password 覆盖掉后端逻辑里的默认值,也可能传一个 id 指定插入。实际开发中应该单独建 DTO 类,只接收业务需要的字段。用 VSCode 写这种 DTO 时,可以右键生成 getter/setter,Java 插件自带的 Source Action 功能能省不少重复劳动。
5. 运行调试与常见问题排查
5.1 运行和调试配置
VSCode 里运行 Spring Boot 有两种方式:最简单的直接用 Spring Boot Dashboard 点启动按钮,适合日常跑服务;想打断点调试就用 Debug 配置。
spring-boot-dashboard 插件的界面我在第 2 章提过,侧边栏能看到所有在 VSCode 里打开的 Spring Boot 项目,每个项目下面有 Start、Restart、Stop、Open Log 按钮。实际体验下来,日志输出直接内联在面板里,格式和终端差不多,但不用来回切换窗口,效率高不少。
如果要用 launch.json 做精细调试配置,可以这样写:
{ "version": "0.2.0", "configurations": [ { "type": "java", "name": "Debug Spring Boot Demo", "request": "launch", "mainClass": "com.example.demo.DemoApplication", "projectName": "demo", "args": "--spring.profiles.active=dev", "env": { "JAVA_TOOL_OPTIONS": "-Dfile.encoding=UTF-8" } } ] }mainClass 要填启动类的全限定名,projectName 填 pom.xml 里的 artifactId。配置好后按 F5 就能带断点启动。Debug 界面上可以实时查看变量的值,也可以直接在 Watch 窗口输入表达式计算。
VSCode 的 Java 调试还支持热部署相关配置。如果你引入了 spring-boot-devtools,在调试模式下修改代码保存后,VSCode 默认会重新编译并触发应用自动重启,这个流程跑通之后开发效率提升非常明显。
5.2 高版本 Spring Boot 踩坑
热词里“springboot版本太高”提得非常多,我推测大多数情况是这么几个表现:
启动直接报错,或者编译错误。最常见的是 Spring Boot 3.x 用了 jakarta 命名空间,代码里还在引 javax。另一个常见的是 JDK 版本不够,3.x 必须 JDK 17,如果系统里默认 JDK 是 8,启动时会提示 UnsupportedClassVersionError。
配置项变化。比如 2.x 里的 spring.redis 配置到 3.x 变成了 spring.data.redis;spring.cloud 某些组件也是类似情况。这些迁移点在官方文档有迁移指南,但实际项目里依赖复杂时很难一下全改对。我排查这类问题时的做法是:先在 VSCode 的终端里执行 mvn clean compile,把编译错误全部暴露出来,错误消息里通常能定位到是哪个依赖引了旧命名空间。
还有一类“版本太高”其实不是 Boot 的问题,而是依赖冲突。比如你选了 Boot 3.2,但某个第三方库还是基于 Boot 2.x 开发的,它的传递依赖可能引入了旧版本的 spring-beans 或 spring-core,导致运行时出现 NoSuchMethodError。这种问题在 VSCode 侧边栏的 Maven 依赖树里最容易发现——把 spring-beans 那一行展开,看版本是不是被覆盖了,然后到 pom.xml 里用 dependencyManagement 强制指定正确版本。
5.3 常见问题速查表
我把这几年用 VSCode 写 Spring Boot 遇到的问题整理成一张表:
| 问题现象 | 排查思路 | 解决办法 |
|---|---|---|
| 控制台输出中文乱码 | 项目编码和控制台编码不一致 | VSCode 设置中搜索 consoleEncoding,改为 UTF-8;同时给 JVM 加 -Dfile.encoding=UTF-8 |
| 启动后访问 404 | 启动类包层级不对,组件没被扫描到 | 打开启动类,确认 Controller 在启动类所在包的子包下 |
| 端口被占用 | 上次启动的服务没停止 | 改用其他端口或清理进程 |
| VSCode 提示找不到主类 | Java 语言服务器索引没建好 | Ctrl+Shift+P 执行 Java: Clean Java Language Server Workspace |
| 扩展市场访问异常或反复要求登录 | 扩展源、代理或账号设置问题 | 检查 VSCode 代理设置,确认扩展市场 URL 配置正确 |
| Lombok 生成的代码标红 | 缺少 Lombok 插件或依赖未刷新 | 安装 Lombok Annotations Support,并在 Maven 面板刷新依赖 |
| 接口返回 500 但日志没输出 | 日志级别太高 | 在 application.yml 设置 logging.level.root 和 logging.level.com.example 查看具体异常信息 |
乱码问题值得单独强调。很多项目代码文件都是 UTF-8,但 Windows 控制台默认用 GBK,运行 Spring Boot 时打印的日志中文全变成乱码。这个问题的根源是 JVM 的默认 file.encoding 跟随系统区域设置,给 VSCode 的运行终端设置环境变量 JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8 就能彻底解决。
5.4 我用下来的几个小技巧
最后分享几个我每天都会用到的小技巧。
第一个是代码片段。VSCode 支持把常用的 Spring Boot 代码片段存成 snippet,比如 @RestController + @RequestMapping 的组合、@Service + @Slf4j 的组合。我在 settings.json 里存了几十条,写新接口时输入 rc 前缀直接生成标准 Controller 骨架,再把方法填进去,效率比从空文件开始写高不少。
第二个是保存后自动整理 import。VSCode 里 Ctrl+Shift+P 输入“保存时操作”,把 Organize Imports 和 Format 都勾上。Java 里 import 经常比代码还长,这个设置让我少了很多手动删无用 import 的活。
第三个是把终端选择为 Git Bash 或 WSL 终端。Windows 上默认终端是 cmd,裁剪命令、日志搜索都难受。VSCode 的设置里可以直接把默认终端改成 Git Bash,所有项目的命令操作体验都会统一。
第四个是用 .http 文件做接口测试。装 REST Client 插件后在项目里建 request.http,写好请求头和请求体,点击 Send Request 就能在同一个窗口里看到响应。开发 Controller 时我基本都是这样联调的,比 Postman 轻量得多,而且请求文件可以跟着项目走,新同事拉下来就能直接用。
根据我个人经验,VSCode 写 Spring Boot 这套组合最大的价值不是让你抛弃 IDEA,而是给了一个更轻量、更自由的选择。工具是为人服务的,别被“一定要用某个 IDE”的惯性绑住。你可以根据项目大小、自己对编辑器的熟悉程度来决定到底用哪套方案,甚至两个都留着。最后再建议一个事:遇到 VSCode 开发 Java 的疑难杂症,先去检查语言服务器工作区状态,这能解决一半以上的玄学问题。