Java 程序员的 AI 进化论 | 用 AI 生成 Spring Boot 脚手架,省下两小时重复劳动
上周新项目启动, Tech Lead 说「先把脚手架搭起来,下周一能跑就行」。以前这种活我至少得花半天------建包结构、写配置类、搞异常处理、加 Swagger 文档、配日志格式,一套下来脑子都木了。这次我换了个思路,直接让 AI 帮我生成。
结果从输入需求到项目能跑起来,总共花了不到 20 分钟。不是那种「生成一堆模板代码然后手动修半天」的 20 分钟,是真正能启动、能访问接口、能打日志的 20 分钟。

一、为什么脚手架值得用 AI 生成
老实讲,脚手架代码是最不该人手写的东西。它没有业务逻辑难度,但量大、碎、容易漏。我之前每次搭项目都要对着上个项目的目录抄一遍,改包名、改配置、删掉不用的依赖,光是确认这些零碎东西就要 40 分钟。
传统方式有几种选择,但各有各的问题:
| 方式 | 耗时 | 问题 |
|---|---|---|
| 手动建包抄代码 | 40-60 分钟 | 容易漏文件,包名改错 |
| Spring Initializr | 15 分钟 | 只生成空壳,业务骨架全得手写 |
| 拷贝旧项目改 | 30 分钟 | 残留旧代码,依赖冲突 |
| AI 生成完整骨架 | 15-20 分钟 | 需要好的 Prompt,但结构最完整 |
Spring Initializr 生成的东西大家都用过,一个 Application 启动类加上 application.yml,然后呢?统一异常处理要自己写吧,响应包装要自己写吧,Swagger 配置要自己写吧。这些东西 AI 能一次性全给你生成出来,而且风格统一。
关键是你要会「点菜」------把需求说清楚,AI 才知道给你生成什么。
二、Prompt 模板设计
我踩过的最大的坑就是:Prompt 写得太笼统,AI 生成的代码跟你想要的对不上。一开始我就写了句「帮我生成一个 Spring Boot 项目脚手架」,结果给我返回了一堆 main 方法里打印 Hello World 的东西,完全没法用。
后来我总结了一个 Prompt 模板,分五个要素,生成的质量直接上了一个台阶:
text
角色:你是资深 Java 架构师,精通 Spring Boot 3.x
任务:生成一个完整的 Spring Boot 项目脚手架
技术栈:Java 17、Spring Boot 3.2、MyBatis-Plus、PostgreSQL
项目结构要求:
- com.example.demo (根包)
- controller / service / mapper / entity / config / common
功能要求:
1. 统一响应体 Result<T>,含 code、message、data
2. 全局异常处理 GlobalExceptionHandler,捕获 BusinessException 和系统异常
3. Swagger 文档配置(springdoc-openapi)
4. 一个示例 CRUD 接口(User 实体的增删改查)
5. application.yml 含数据源、日志、Swagger 配置
约束:包名 com.example.demo,端口 8080
这个模板的核心思路是「五要素法」:角色定位、任务描述、技术栈、结构要求、功能清单。缺任何一个,生成质量都会打折扣。
三、生成的项目结构
用上面那个 Prompt,AI 生成的项目结构长这样:
text
demo/
├── src/main/java/com/example/demo/
│ ├── DemoApplication.java
│ ├── common/
│ │ ├── Result.java
│ │ └── ResultCode.java
│ ├── config/
│ │ ├── SwaggerConfig.java
│ │ └── MyBatisPlusConfig.java
│ ├── controller/
│ │ └── UserController.java
│ ├── entity/
│ │ └── User.java
│ ├── exception/
│ │ ├── BusinessException.java
│ │ └── GlobalExceptionHandler.java
│ ├── mapper/
│ │ └── UserMapper.java
│ └── service/
│ ├── UserService.java
│ └── impl/UserServiceImpl.java
├── src/main/resources/
│ ├── application.yml
│ └── mapper/UserMapper.xml
└── pom.xml
这个结构是我觉得比较舒服的分层方式。common 放公共类,config 放配置类,exception 单独拎出来放异常相关的东西。有些人喜欢把异常塞到 common 里,我习惯分开,因为异常类多了以后混在一起不好找。
生成的核心代码质量也不错,我挑几个关键类看看。
3.1 统一响应体
java
package com.example.demo.common;
import lombok.Data;
@Data
public class Result<T> {
private Integer code;
private String message;
private T data;
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>();
result.setCode(200);
result.setMessage("操作成功");
result.setData(data);
return result;
}
// 失败响应,code 从 ResultCode 枚举取,别硬编码数字
public static <T> Result<T> fail(Integer code, String message) {
Result<T> result = new Result<>();
result.setCode(code);
result.setMessage(message);
return result;
}
}
这段代码我基本没改。有个小细节:失败方法我让它接受 code 和 message 两个参数,而不是直接传 ResultCode 枚举。因为有些场景错误码是动态的(比如第三方接口返回的 HTTP 状态码),枚举覆盖不全。
3.2 全局异常处理
java
package com.example.demo.exception;
import com.example.demo.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
// 业务异常单独捕获,返回 200 + 业务错误码,前端判断 code 字段
@ExceptionHandler(BusinessException.class)
public Result<Void> handleBusinessException(BusinessException e) {
log.warn("业务异常: {}", e.getMessage());
return Result.fail(e.getCode(), e.getMessage());
}
// 参数校验异常,把字段错误信息拼出来方便排查
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<Void> handleValidException(MethodArgumentNotValidException e) {
String msg = e.getBindingResult()
.getFieldErrors()
.stream()
.map(err -> err.getField() + ": " + err.getDefaultMessage())
.reduce((a, b) -> a + "; " + b)
.orElse("参数校验失败");
log.warn("参数校验异常: {}", msg);
return Result.fail(400, msg);
}
// 兜底:其他异常统一返回 500,别把堆栈抛给前端
@ExceptionHandler(Exception.class)
public Result<Void> handleException(Exception e) {
log.error("系统异常", e);
return Result.fail(500, "系统内部错误");
}
}
这里有个踩坑经验要分享。第一次生成的版本里,BusinessException 的 handler 没有 log.warn,导致业务异常被 Exception 的兜底 handler 的 log.error 打了完整堆栈。日志里全是 WARN 级别的业务异常堆栈,每天几百条,排查真正的问题时特别烦。后来我手动加了日志级别区分------业务异常用 warn,系统异常用 error,日志清爽多了。
3.3 依赖配置
依赖这块我改了一些,AI 默认给的版本有时候不是最新的。以下是我实际使用的依赖清单:
| 依赖 | groupId | artifactId | 版本 | 作用 |
|---|---|---|---|---|
| Spring Boot Web | org.springframework.boot | spring-boot-starter-web | 3.2.5 | Web 框架 |
| MyBatis-Plus | com.baomidou | mybatis-plus-spring-boot3-starter | 3.5.5 | ORM 增强 |
| PostgreSQL 驱动 | org.postgresql | postgresql | 42.7.3 | 数据库驱动 |
| springdoc-openapi | org.springdoc | springdoc-openapi-starter-webmvc-ui | 2.3.0 | Swagger 文档 |
| Lombok | org.projectlombok | lombok | 1.18.32 | 简化代码 |
| validation | org.springframework.boot | spring-boot-starter-validation | 3.2.5 | 参数校验 |
四、踩坑经验
4.1 包名不一致导致扫描失败
AI 生成代码的时候,有时候同一个类在不同的消息轮次里,包名会变。比如第一轮生成的 UserController 包名是 com.example.demo.controller,第二轮生成的 UserService 包名变成了 com.example.demo.service.impl 但 import 路径写的是 com.example.demo.service.UserService。
这个问题如果项目小还好排查,项目一大就坑死你。我的建议是 Prompt 里把包名写死,而且生成完之后先跑一遍编译,有 import 错误立刻能发现。
| 常见包名问题 | 现象 | 解决方案 |
|---|---|---|
| 包名漂移 | 编译报错找不到符号 | Prompt 中明确写死根包名 |
| import 路径错 | IDE 标红但能自动修复 | 统一用 IDE 的 organize imports |
| 同名类冲突 | 两个包下有同名类 | 生成时指定类名前缀或后缀 |
4.2 Swagger 版本不匹配
第二个坑是 Swagger 的版本。Spring Boot 3.x 之后,老的 Springfox 不支持了,必须用 springdoc-openapi。AI 如果没有在 Prompt 里明确技术栈版本,有概率给你生成 Springfox 的配置类,编译直接报错。
java
// 错误写法:Spring Boot 3 下不兼容,编译报错
// @EnableSwagger2 ← 这个注解在 Spring Boot 3 里找不到
// SwaggerConfig 继承 Docket ← Docket 类已废弃
// 正确写法:springdoc-openapi,零配置即可
package com.example.demo.config;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI openAPI() {
return new OpenAPI()
.info(new Info()
.title("Demo API")
.description("AI 生成的 Spring Boot 脚手架接口文档")
.version("1.0.0"));
}
}
springdoc-openapi 比老 Springfox 简单太多了,基本上只要引入依赖就能用,配置类只是加个文档描述信息。别让 AI 用旧版本糊弄你 ,Prompt 里一定要写清楚 springdoc-openapi 而不是 Swagger 或 Springfox。
五、效率对比
我把这次用 AI 生成脚手架跟之前手动搭的经历做了个对比,数据比较真实:
| 环节 | 手动搭建 | AI 生成 | 节省时间 |
|---|---|---|---|
| 项目结构创建 | 15 分钟 | 1 分钟 | 14 分钟 |
| 配置类编写 | 20 分钟 | 2 分钟 | 18 分钟 |
| 异常处理框架 | 15 分钟 | 3 分钟 | 12 分钟 |
| 示例 CRUD 接口 | 25 分钟 | 5 分钟 | 20 分钟 |
| Swagger 文档配置 | 10 分钟 | 2 分钟 | 8 分钟 |
| 调试与修复 | 10 分钟 | 7 分钟 | 3 分钟 |
| 合计 | 95 分钟 | 20 分钟 | 75 分钟 |
省了 75 分钟,差不多一个半小时。注意「调试与修复」那行------AI 生成不是零成本,你得花时间检查包名、版本、依赖冲突这些问题。但跟纯手写比,调试时间还是短了很多。
六、Prompt 调优建议
用了一个月下来,我发现 Prompt 质量直接决定生成质量。有几个调优技巧值得分享:
技巧一:给约束比给自由更重要。 Prompt 里写「端口 8080」「包名 com.example.demo」这种硬约束,比写「请合理设计端口」效果好得多。AI 不擅长猜你的偏好,你不说它就自己编。
技巧二:分轮生成比一次性生成好。 如果一次性让 AI 生成全部 10 个类,后面的类质量会下降(上下文太长,注意力分散)。我的做法是分三轮:第一轮生成基础结构(Result、Exception、Config),第二轮生成业务代码(Controller、Service、Mapper),第三轮生成配置文件和依赖。每轮只关注一件事,质量高很多。
技巧三:生成后必须编译验证。 AI 生成的代码可能有 90% 是对的,但那 10% 的错误(包名漂移、版本不匹配、import 缺失)会要你的命。跑一遍 mvn compile,有错立刻修,别攒着。
技巧四:用示例锚定风格。 AI 生成代码风格的稳定性不是太好,尤其是多轮对话之后容易跑偏。我会在 Prompt 里加一段示例代码,AI 会照着这个风格生成后续内容。比如:
java
// 示例代码风格
@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@GetMapping("/{id}")
public Result<User> getById(@PathVariable Long id) {
return Result.success(userService.getById(id));
}
}
把这段示例贴进 Prompt,AI 后续生成的代码风格就跟它对齐了------命名规范、注解位置、构造器注入还是字段注入,全部统一。这种「以例锚定」的方式比口头描述「请用 Lombok 和构造器注入」效果好十倍。
技巧五:避免一次生成太多类。 我设定的上限是单轮生成 8 个类。超过 8 个类,AI 的注意力会分散,后面生成的代码质量明显下降。有时候项目需要 12 个类,我会分两轮:基础类一轮,业务类一轮。
| Prompt 要素 | 不写会怎样 | 写了的好处 |
|---|---|---|
| 角色定位 | 生成新手级代码 | 代码风格成熟,命名规范 |
| 技术栈版本 | 用旧版依赖 | 版本统一,兼容性好 |
| 包名约束 | 包名随机 | 结构清晰,扫描不出错 |
| 功能清单 | 只生成空壳 | 一次性生成完整骨架 |
| 约束条件 | 想到哪写到哪 | 生成结果可控 |
七、总结
用 AI 生成 Spring Boot 脚手架这件事,关键不在于 AI 能不能生成代码,而在于你能不能把需求说清楚。Prompt 写得好,20 分钟出活;写得差,改代码的时间比自己写还长。
| 检查项 | 建议 |
|---|---|
| Prompt 五要素 | 角色、任务、技术栈、结构、功能缺一不可 |
| 包名写死 | 在 Prompt 里明确根包名,防止包名漂移 |
| 分轮生成 | 基础类→业务类→配置,每轮聚焦一个主题 |
| 版本指定 | Spring Boot 3.x 用 springdoc 不用 Springfox |
| 编译验证 | 生成后立刻 mvn compile,有错马上修 |
| 日志分级 | 业务异常 warn,系统异常 error,别混 |
| 响应体设计 | 失败方法接受动态 code,别只用枚举 |
| 依赖表格 | 用 Markdown 表格替代 XML,公众号不兼容 XML |
这套流程我跑了一个月,搭了 4 个新项目的脚手架,每个都 20 分钟以内搞定。当然脚手架只是起点,真正的业务代码还是得自己写。但把重复劳动甩给 AI,省下来的时间用来想业务逻辑,这笔买卖不亏。