用 VSCode 写 Spring Boot 程序,这话放几年前说出来,大概率要被老 Java 开发笑话一句“正经人谁这么干”。但现在情况确实变了——微软联合 Red Hat 和 Spring 官方把扩展补齐之后,VSCode 已经能覆盖日常 Spring Boot 开发的大半需求。我自己的主力机器就是一台 8G 内存的旧笔记本,开 IDEA 能卡半分钟,换成 VSCode 明显清爽不少。这篇文章就把我从装环境到跑通项目、再到集成 Minio 和做签名认证的完整过程记录下来,中间踩过的坑、查过的问题、调过的配置都会讲到。不管是刚开始学 Spring Boot 的新手,还是单纯想给机器减减负的老手,都能从里面找到点能直接用上的东西。
1. 环境准备:先搭一套能跑 Spring Boot 的 VSCode 工具链
在正式开始写代码之前,得先把基本的工具链准备好。这一步看起来简单,但恰恰是最容易出问题的地方——很多人兴冲冲装好 VSCode,结果代码跑不起来,回头一看是 JDK 版本对不上,或者是 Maven 仓库没配镜像,下载依赖能等半小时。下面我按自己的实际操作顺序来讲,每一步都说说“为什么这么做”。
1.1 为什么我推荐用 VSCode 开发 Spring Boot
先说句公道话:如果你在一个大型企业项目里,团队统一用 IDEA,几十个模块互相依赖,信息架构复杂,那我还是建议你用 IDEA,它的重构、智能提示和 Spring 生态支持确实更完善。但如果你是在做中小型项目、个人项目、或者学习阶段的项目,VSCode 完全够用。甚至在某些场景下,VSCode 比 IDEA 更舒服。
第一个优势是启动速度。IDEA 打开一个大型工作区,加载索引、扫描 Maven 依赖,少说几十秒;而 VSCode 本身就是为轻量设计的,打开一个 Spring Boot 项目基本能做到秒开。第二个优势是资源占用。8G 内存的旧电脑跑 IDEA 会显得吃力,但 VSCode 加几个 Java 插件,内存占用通常在 1G 到 2G 之间,运行起来明显流畅。第三个优势是免费,Spring Boot 相关的完整开发能力不需要买任何授权,IDEA 虽然有免费的社区版,但社区版对 Spring 原生支持要弱一些。
还有一点很容易被忽略:VSCode 对所有语言一视同仁。你可以在同一个编辑器里做前端 Vue 开发、写 Python 脚本、跑数据库工具,还能顺便看 Markdown 文档,不用在多个 IDE 之间来回切换。对于习惯全栈开发的人来说,这种“一个编辑器管所有事”的体验非常舒服。
1.2 安装 VSCode 与核心插件
安装 VSCode 本身没有太多技术含量,官网下载对应的系统版本,一路下一步就行。重点说一下安装之后的插件配置。我建议不要一次性装一堆花里胡哨的插件,而是按项目需要来。
必需的插件有这么几个:
- Extension Pack for Java,这是微软官方出的 Java 全家桶,包含语言支持、调试器、测试器和 Maven 支持,装这一个就覆盖了基础的 Java 开发能力。
- Spring Boot Extension Pack,包含 Spring Initializr、Spring Boot Dashboard、Spring Tools,专门为 Spring Boot 开发准备。
- Lombok Annotations Support,如果你的项目用了 Lombok,这个插件必须装,否则 @Data、@Slf4j 这些注解会标红,编译也会报错。
这几个插件装完之后,VSCode 会在右下角提示你配置 Java 环境和 Maven,按照提示操作就行。对了,还有一个小技巧:项目里如果用了 Maven 的 wrapper,也就是 mvnw,VSCode 会自动识别并使用它,这样不需要本地装 Maven 也能构建项目。不过我还是推荐本地装一个 Maven,因为用 Maven 命令做打包、清理、发布操作会更直观。
1.3 JDK 与 Maven 的配置,这一步最容易踩坑
JDK 的选择要跟着 Spring Boot 版本走。Spring Boot 3.x 要求 JDK 17 或更高,Spring Boot 2.7 及之前的版本则用 JDK 8 或 11 就行。我之前就吃过这个亏:机器上装的是 JDK 11,去网上找了个 Spring Boot 3.2 的项目代码,一跑直接报“Unsupported class file major version 61.0”,折腾半天才发现是 JDK 版本不够。所以我的建议是先把 JDK 17 装好,目前这是最稳妥的选择,既能跑 Spring Boot 2.x(部分版本需要兼容处理),又能跑 Spring Boot 3.x。
Windows 上配环境变量没什么可说的,新建 JAVA_HOME 指向 JDK 安装目录,然后在 Path 里加上%JAVA_HOME%\bin,最后在命令行里敲java -version验证一下。Linux 和 macOS 都差不多,无非是改/etc/profile或者~/.zshrc。
Maven 的配置同样重要。首先是 settings.xml,里面最值得改的是本地仓库路径和镜像源。默认本地仓库在用户目录下的.m2/repository,如果你 C 盘空间紧张,可以改到其他盘。镜像源我用的是国内公共仓库,配置很简单,在 settings.xml 的 mirrors 节点里加一段:
<mirror> <id>mavenpublic</id> <mirrorOf>*</mirrorOf> <url>https://maven.aliyun.com/repository/public</url> </mirror>加上之后,下载依赖的速度肉眼可见地提升。这里要记住一个原则:JDK 版本、Maven 版本、Spring Boot 版本三者之间要匹配,不要贪新。Maven 3.6 以上基本够用,能配合 Spring Boot 2.7 和 3.x 使用。
2. 创建 Spring Boot 项目:两种方式任选
环境准备好了,接下来就进入到创建项目这一步。这里我介绍两种方式,一种是在 VSCode 内部直接生成,一种是去 Spring Initializr 网站生成后导入。两种方式最终执行的效果一样,看你自己习惯。
2.1 方式一:VSCode 内置的 Spring Initializr
装完 Spring Boot Extension Pack 后,VSCode 里就多了一个“Spring Initializr”命令。按 Ctrl+Shift+P 打开命令面板,输入“Spring Initializr”,选择“Create a Maven Project”。然后它会一步步问你:
- Spring Boot 版本,我建议选择当前主流的 3.x 版本,除非你有特殊原因需要 2.7。
- 开发语言选 Java。
- Group 填写公司域名反转,比如 com.example。
- Artifact 填写项目名,比如 demo。
- 依赖让你多选,这里可以按需勾选。
选完之后它会在你指定的目录下生成一个完整项目骨架,同时在 VSCode 中自动打开。第一次打开时会后台下载依赖,右下角会有进度提示,千万别急着写代码,等它下载完再说。这里我补充一个细节:VSCode 生成的默认目录结构很适合新手,入口类、配置文件、测试目录都已经摆好了,你要做的就是往里填业务代码。
2.2 方式二:直接去 start.spring.io 生成
相信很多人都用过 start.spring.io 这个网站,它其实就是一个可视化的 Spring Boot 项目生成器。浏览器打开之后同样要选择 Maven/Gradle、语言、版本、依赖等信息,选好之后点 Generate 下载一个 zip 压缩包。解压之后,用 VSCode 打开这个文件夹,会自动识别为一个 Maven 项目。
这个方式唯一的好处是网站页面上的依赖选择列表更直观,能看到每个依赖的作用。另外,如果你要批量生成多个不同配置的项目,网站更方便。其余操作和在 VSCode 里生成是一样的。还有一个小注意点:如果下载的 zip 解压后是带目录层级的那种,比如 docker/ 目录里有项目文件,直接用 VSCode 打开最外层的文件夹会把根目录搞错,建议打开包含 pom.xml 的那一层。
2.3 项目结构拆解:先看懂这些目录再动手
一个标准的 Spring Boot 项目用 Maven 管理,核心目录结构如下:
demo/ ├── pom.xml ├── src/main/java/com/example/demo/ │ └── DemoApplication.java ├── src/main/resources/ │ ├── application.properties │ ├── static/ │ └── templates/ └── src/test/java/pom.xml 是整个项目的依赖清单和构建脚本,Spring Boot 依赖管理、第三方库都靠它。src/main/java 下是业务代码,启动类 DemoApplication 是程序的入口。resources 文件夹存放配置文件和静态资源。
我刚接触 Spring Boot 时最大的困惑是:为什么启动类放在最外层包,而且其他 Controller、Service 都要放在启动类的子包下?原因是 Spring Boot 默认从启动类所在的包开始扫描 Bean。如果 Controller 放在其他包下,比如 com.example.controller,而启动类在 com.example.demo,那么扫描不到,接口就 404。所以项目结构上,所有需要交给 Spring 管理的类,都要放在启动类所在包的子包下面。
3. 核心开发环节与配置:跑通第一个 REST API
项目跑通之后,开始写实际业务代码前,有几个核心配置必须先搞清楚。这些内容看着基础,但决定了后面开发顺不顺手。
3.1 application.yml 的常用配置
Spring Boot 支持 application.properties 和 application.yml 两种配置文件,我个人更喜欢 yml,层级清晰,不容易写乱。一个常见的配置长这样:
server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/demo_db username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver profiles: active: dev端口可以随便改,但要注意操作系统是否占用了。datasource 配置数据库连接,注意 Spring Boot 2.x 和 3.x 的 MySQL 驱动写法有细微差别,2.x 的驱动类名是 com.mysql.cj.jdbc.Driver,3.x 默认用 com.mysql.cj.jdbc.Driver 也可以,但新版更推荐直接使用 HikariCP 连接池。
关于多环境配置,一个常用的做法是把配置文件拆成 application-dev.yml、application-prod.yml,然后在主配置里切换 active。比如本地用 dev 环境连接开发库,上线时用 prod 环境连接线上库。这个切换成本非常低,但能避免很多环境不一致的坑。
3.2 写一个最简 REST API
新建一个 Controller 类:
@RestController @RequestMapping("/api/v1") public class HelloController { @GetMapping("/hello") public String hello() { return "Hello from VSCode Spring Boot"; } }写完这段代码后,在 VSCode 的 Spring Boot Dashboard 面板里找到项目,点击启动按钮。日志出现 “Started DemoApplication” 后就说明启动成功了。浏览器访问http://localhost:8080/api/v1/hello,能看到返回的字符串。
这里有个小细节:Spring Boot 3.x 里,Controller 的注解还是那套,但底层已经用 Jakarta EE 替代了原来的 javax。如果你从旧项目里复制代码,看到javax.servlet、javax.validation之类的包,在 3.x 下编译会报错,需要改成jakarta前缀。这个事我遇到过不止一次,从网上复制一段旧代码下来,编译直接标红,很多人一时间反应不过来。
3.3 热重载配置:改代码不用手动重启
开发期间最烦的就是每次改个方法都要重启项目,等启动日志等半天。Spring Boot 官方提供 spring-boot-devtools,加上它之后,代码变更会自动重启应用。pom.xml 里加依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency>加上依赖后,VSCode 里还需要开启“自动构建”。设置里搜索“Java > Import”或者直接按快捷键 Ctrl+Shift+P,输入 “Java: Clean Java Language Server Workspace”,提示重载后生效。
不过 devtools 也有副作用。最典型的场景是加了依赖、改了启动类参数之类的东西,devtools 偶尔会触发不了重启,这时候手动重启一下项目反而更快。生产环境的 jar 包里默认不会包含 devtools,所以不用担心影响到部署。
3.4 调试:断点不是 IDEA 的专利
VSCode 里调试 Java 项目也一样支持断点。在方法所在行号左边点击,加一个红点,然后按 F5,或者点击菜单栏的 Run 和 Debug,选择 Java 环境。项目会以调试模式启动,执行到断点处就会暂停,可以查看变量的值、调用栈。在左侧面板还能监视表达式。
调试配置在.vscode/launch.json文件里,如果你没这个文件,VSCode 会在第一次调试时自动生成。默认情况下选“Debug Java”配置就能跑,不过要注意,调试前最好先停掉之前手动启动的实例,否则端口会被占用。还需要注意的是,launch.json 里的启动类路径要指向正确的 DemoApplication。
4. 常用集成场景:从对象存储到身份认证
Spring Boot 单跑一个 Hello World 没什么意义,实际项目中总要和各种中间件打交道。这里挑两个我实际做过的集成场景讲,一个是 Minio 对象存储,一个是基于 JWT 的签名认证,都是网上问得非常多的问题。
4.1 Minio 加入到 Spring Boot:对象存储接入实战
Minio 是一个开源的对象存储服务,可以用来做文件存储,比如上传头像、上传图片附件等。集成方式比较直接,首先引入依赖,我用的是 io.minio 提供的 Java SDK:
<dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>8.5.7</version> </dependency>然后在配置文件里加上 Minio 的地址和密钥:
minio: endpoint: http://localhost:9000 access-key: admin secret-key: admin123 bucket-name: demo-bucket接着写一个配置类,把 MinioClient 初始化为一个 Bean:
@Configuration public class MinioConfig { @Value("${minio.endpoint}") private String endpoint; @Value("${minio.access-key}") private String accessKey; @Value("${minio.secret-key}") private String secretKey; @Bean public MinioClient minioClient() { return MinioClient.builder() .endpoint(endpoint) .credentials(accessKey, secretKey) .build(); } }之后在 Service 里注入 MinioClient,调用putObject、getObject等方法就能做上传下载。新手容易踩的坑有两个:一是忘了提前创建 bucket,用的时候会报找不到桶;二是上传文件的 Content-Type 没设置,导致前端下载下来的文件名和类型不对。可以单独封装一个 FileService,把建桶、上传、生成访问链接这些操作统一管理,避免到处写 SDK 调用。
4.2 基于 JWT 做签名认证
很多接口都需要登录后才能访问,常见方案就是 JWT 签发给前端,前端请求时带上 token,后端拦截器校验 token。这是 Spring Boot 面试里高频出现的问题。
一个最小可用的流程是:登录接口验证用户名密码,验证通过后用 hmac 算法生成 token;写一个拦截器或者过滤器,从请求头 Authorization 里取 token,解析并校验签名;如果通过就放行,否则返回 401。JWT 库我用的是 jjwt 家的,依赖很小,配置也不复杂。签名密钥建议放在配置文件里统一管理,需要切换时只改一处。
还有一点安全建议:签名密钥不要直接写成明文放在 application.yml 里,至少要用环境变量方式注入,或者放到配置中心里。开发环境偷懒可以写死,上线前一定要换掉。另外,token 过期时间也不要设置太长,常见的做法是登录后返回 token 和 refresh token,短 token 过期后用 refresh token 换新,这样用户不用频繁重新登录。
4.3 顺手补充两个问得多的集成
网上搜“springboot整合activemq”、“springboot整合flink”的也非常多。ActiveMQ 是经典的消息中间件,Spring Boot 用 spring-boot-starter-activemq 这个依赖,然后配置 broker-url 和账号密码,就可以用 JmsTemplate 收发消息了。Flink 的情况特殊,它不是 Spring 生态的东西,一般是把 Spring Boot 项目打包成 jar,然后在 Flink 作业里通过自定义函数来加载,开发时适配起来会比普通中间件麻烦一些。这类集成的核心思路都是“先引入依赖,再配置连接参数,最后把客户端封装成 Bean”,掌握这个套路,遇到没见过的中间件也能快速入门。
5. 常见问题排查与避坑心得
这一章写我实际踩过的坑,以及网上咨询频率很高的问题。如果能提前看完,能省不少时间。
5.1 Spring Boot 版本太高,项目跑不起来
很多时候项目跑不起来就是版本问题。Spring Boot 3.x 相比 2.x 改动很大,最直观的变化是 JDK 最低要求 17,另外包名从 javax 改成 jakarta,还有很多第三方组件适配进度不一致。如果你在网上找了一个 3.x 的项目,本地 JDK 却是 8 或 11,直接编译不过。
解决思路有三个方向:升级 JDK 到 17 以上;或者把项目降级到 2.7.x 并调整依赖;或者找一个和当前环境匹配的项目源码。我个人的建议是如果是新项目,直接上 JDK 17 加 Spring Boot 3.x,反正都是新东西,直接用新版最省事。下表是常见的版本匹配关系,可以存一份参考。
| 环境组合 | Spring Boot 2.x | Spring Boot 3.x |
|---|---|---|
| JDK 版本 | 8/11 | 17 或更高 |
| javax/jakarta 包名 | javax | jakarta |
| 推荐 Maven | 3.6+ | 3.6+ |
| 常见 starter 兼容性 | 成熟 | 部分组件仍需升级 |
5.2 自动装配原理与“Bean 找不到”问题
面试必问的 Spring Boot 自动装配原理,其实可以简单理解为:Spring Boot 在启动时会加载META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件里的自动配置类,然后根据当前项目的依赖和配置,判断是否启用某些配置。这就是为什么引入一个 redis 的 starter 依赖后,什么都不用做就能直接用 RedisTemplate。
开发中遇到最典型的报错是 “Field xxx in Service required a bean of type xxx that could not be found”。原因无非这几类:类上没有加注解(比如漏了 @Service、@Repository);类没有放到启动类子包下导致扫描不到;依赖没引入;多个实现时没指定 @Qualifier。排查时优先按这四类去查,大概率能定位。
5.3 端口占用:重启项目报端口被占用
VSCode 里调试 Java 项目,最常出现一个现象:上次运行没停干净,再次运行时报Web server failed to start. Port 8080 was already in use。解决方式是找到占用进程并杀掉。Windows 下用netstat -ano | findstr :8080查到 PID,然后在任务管理器里结束进程;Linux/macOS 用lsof -i :8080,然后kill -9 PID。
还有一个更隐蔽的坑:devtools 热重启偶尔会让旧进程残留,导致端口冲突。遇到这种情况,可以把运行中的项目全部停止,再重新启动一次。如果是在部署环境遇到端口占用,还需要检查是否有其他服务占用了同样的端口,建议在运维侧统一规划端口分配。
5.4 VSCode 开发体验的几点优化
用 VSCode 开发 Java 时,如果你发现没有代码提示、没有自动导入、或者文件一直被自动关闭,大概率是 Java 语言服务没正常工作。可以打开命令面板,执行 “Java: Clean Java Language Server Workspace”,让语言服务重新初始化;如果还不行,就删除项目根目录下的 .vscode 文件夹和.metadata之类的缓存后重新打开。另外,针对“没有编辑的文件会被自动关上”这个问题,这个其实是编辑器 Tab 管理的特性,可以在设置里搜索 “workbench.editor.enablePreview”,关掉预览模式,这样双击打开的文件就不会因为打开下一个文件而自动关闭了。
我在实际使用中还发现一个优化点:VSCode 的启动速度虽然快,但 Java 语言服务器打开大型项目时,文件监控开销比较大。如果你的项目模块特别多,可以在设置里排除掉不必要的目录,比如 target、node_modules 这些生成目录,语言服务只聚焦在源码上,这样提示和跳转都会快不少。
最后说点我自己的体会。折腾 VSCode 写 Spring Boot 这段时间,最大的收获不是某个快捷键或者某个插件,而是理解了工具只是辅助,真正决定开发效率的是你对项目和框架的熟悉程度。版本冲突、Bean 扫描不到、端口被占用,这些问题看起来是环境问题,本质上都是在提醒你:要清楚自己的项目跑在什么版本上、依赖是什么、入口在哪。把这些基础打牢了,用不用 VSCode,用不用 IDEA,其实都能写得很顺。如果你现在正卡在环境配置,别急,把 JDK、Maven、插件顺序理顺,再小的坑也不过是几分钟的事。