通用的 Spring Boot 工程 skill,不绑定特定机器或项目,换台电脑直接用。 覆盖 Controller-Service-Repository 分层架构、JPA/MyBatis 双数据方案、RESTful API 规范、 Redis 缓存、AOP 日志、全局异常处理、定时任务、事务排查、性能调优。 含环境检测脚本和零硬编码路径设计。 触发关键词:Spring Boot、Java 后端、JPA、MyBatis、Spring Cloud、微服务、 Maven、@Transactional、@Res
Spring Boot 开发专家
功能概述
Spring Boot 开发专家是一项面向实际任务的技能,主要用于通用的、可迁移的 Spring Boot 开发 skill;不绑定特定机器、特定项目——任何 Spring Boot 工程师在任何电脑上都能直接用;
核心要点
- 可迁移性设计;
- 本 skill 遵循零硬编码原则:;
- 只用项目相对路径 src/main/java/... ,绝不用绝对路径;
使用与执行
默认8080,可配 server.port ,不做假设;用 spring.dat。它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。从功能定位来看,该技能强调把分散的操作要求整理成清晰、可复用的处理流程,使用户能够围绕既定目标快速准备输入、选择执行方式并获得结构化结果。实际使用前应先确认任务范围、数据来源、运行环境、必要权限和关键参数,再依据技能说明逐步执行;
结果检查与注意事项
若输入条件不完整,应先补齐信息或采用保守配置,避免因错误假设导致结果偏离需求。执行过程中需要关注工具调用是否成功、接口或依赖是否可用、输出格式是否符合预期,并对异常提示、缺失字段和边界情况进行处理;涉及批量任务时,还应保存进度,避免中断后重复操作。该技能适合用于一次性任务,也可以接入自动化工作流,与其他技能或上层代理配合完成更完整的业务链路;在组合使用时,应明确每一步的输入输出关系,并避免不同步骤之间出现参数冲突。
Spring Boot 开发专家
通用的、可迁移的 Spring Boot 开发 skill。不绑定特定机器、特定项目——任何 Spring Boot 工程师在任何电脑上都能直接用。
可迁移性设计
本 skill 遵循零硬编码原则:
| 原则 | 做法 |
|---|---|
| 路径 | 只用项目相对路径 src/main/java/...,绝不用绝对路径 |
| 端口 | 默认8080,可配 server.port,不做假设 |
| 数据库 | 用 spring.datasource.url 自动检测,不硬编码连接字符串 |
| 环境检测 | 用 java -version、mvn -v 检测工具链 |
| 包名 | 用占位符 ${basePackage} 表示,根据项目实际替换 |
项目初始化
方式一:Spring Initializr(推荐)
# 直接 curl 下载模板项目(任何机器都能跑) curl -s https://start.spring.io/starter.zip -d type=maven-project -d language=java -d bootVersion=3.4.5 -d baseDir=my-project -d groupId=com.example -d artifactId=my-project -d name=MyProject -d description="Spring Boot project" -d packageName=com.example.demo -d packaging=jar -d javaVersion=17 -d dependencies=web,data-jpa,mysql,validation,lombok,devtools -o my-project.zip
方式二:Maven 手动创建
org.springframework.boot spring-boot-starter-parent 3.4.5 org.springframework.boot spring-boot-starter-web
检测现有项目
# 判断是否 Spring Boot 项目 grep -rl "spring-boot-starter" pom.xml build.gradle 2>/dev/null # 获取 Spring Boot 版本 mvn dependency:tree -Dincludes=org.springframework.boot 2>/dev/null | grep "spring-boot-starter"
标准分层架构
src/main/java/${basePackage}/
├── controller/ ← 接口层:@RestController, @RequestMapping
├── service/ ← 业务层:@Service, @Transactional
│ └── impl/ ← 实现类(接口-实现分离时)
├── repository/ ← 数据层:JpaRepository / MyBatis Mapper
├── entity/ ← 实体:@Entity, @Table
├── dto/ ← 数据传输对象(API 入参/出参)
├── vo/ ← 视图对象(返回给前端的)
├── config/ ← 配置类:@Configuration, @Bean
├── interceptor/ ← 拦截器:HandlerInterceptor
├── aspect/ ← 切面:@Aspect, @Around
├── exception/ ← 全局异常处理:@ControllerAdvice
├── util/ ← 工具类
└── constant/ ← 常量/枚举
包名约定: ${basePackage} = groupId + artifactId 的组合,如 com.example.demo
Controller 层规范
RESTful API 模板
@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor
@Slf4j
public class UserController {
private final UserService userService;
@GetMapping
public Result> list(
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "20") int size,
@RequestParam(required = false) String keyword) {
return Result.ok(userService.listUsers(page, size, keyword));
}
@GetMapping("/{id}")
public Result getById(@PathVariable Long id) {
return Result.ok(userService.getById(id));
}
@PostMapping
public Result create(@Valid @RequestBody UserCreateDTO dto) {
return Result.ok(userService.create(dto));
}
@PutMapping("/{id}")
public Result update(@PathVariable Long id, @Valid @RequestBody UserUpdateDTO dto) {
userService.update(id, dto);
return Result.ok();
}
@DeleteMapping("/{id}")
public Result delete(@PathVariable Long id) {
userService.delete(id);
return Result.ok();
}
}
统一返回格式
@Data @NoArgsConstructor @AllArgsConstructor public class Result{ private int code; private String message; private T data; public static Result ok() { return new Result<>(200, "success", null); } public static Result ok(T data) { return new Result<>(200, "success", data); } public static Result fail(int code, String msg) { return new Result<>(code, msg, null); } } @Data public class PageResult { private long total; private int page; private int size; private List records; }
全局异常处理
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result handleValidation(MethodArgumentNotValidException e) {
String msg = e.getBindingResult().getFieldErrors().stream()
.map(FieldError::getDefaultMessage)
.collect(Collectors.joining(", "));
return Result.fail(400, msg);
}
@ExceptionHandler(BusinessException.class)
public Result handleBusiness(BusinessException e) {
return Result.fail(e.getCode(), e.getMessage());
}
@ExceptionHandler(Exception.class)
public Result handleUnknown(Exception e) {
log.error("Unhandled exception", e);
return Result.fail(500, "Internal server error");
}
}
Service 层规范
public interface UserService {
PageResult listUsers(int page, int size, String keyword);
UserVO getById(Long id);
Long create(UserCreateDTO dto);
void update(Long id, UserUpdateDTO dto);
void delete(Long id);
}
@Service
@RequiredArgsConstructor
@Slf4j
public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
@Override
@Transactional(readOnly = true)
public PageResult listUsers(int page, int size, String keyword) {
Page userPage = userRepository.findByKeyword(keyword, PageRequest.of(page - 1, size));
return new PageResult<>(
userPage.getTotalElements(), page, size,
userPage.getContent().stream().map(UserVO::from).toList()
);
}
@Override
@Transactional
public Long create(UserCreateDTO dto) {
if (userRepository.existsByEmail(dto.getEmail())) {
throw new BusinessException(400, "邮箱已被注册");
}
User user = User.from(dto);
return userRepository.save(user).getId();
}
// ... 其余方法
}
Repository 层规范
JPA
@Repository public interface UserRepository extends JpaRepository{ boolean existsByEmail(String email); @Query("SELECT u FROM User u WHERE u.name LIKE %:keyword% OR u.email LIKE %:keyword%") Page findByKeyword(@Param("keyword") String keyword, Pageable pageable); @Modifying @Query("UPDATE User u SET u.status = :status WHERE u.id IN :ids") int batchUpdateStatus(@Param("status") int status, @Param("ids") List ids); }
MyBatis-Plus
@Mapper public interface UserMapper extends BaseMapper{ @Select("SELECT * FROM user WHERE email = #{email}") User selectByEmail(@Param("email") String email); List selectPageWithOrders(@Param("keyword") String keyword, Page page); }
实体规范
@Entity
@Table(name = "user")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 50)
private String name;
@Column(nullable = false, unique = true, length = 100)
private String email;
@Column(nullable = false)
private Integer status = 1; // 1=正常 0=禁用
@CreatedDate
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updatedAt;
public static User from(UserCreateDTO dto) {
User user = new User();
BeanUtils.copyProperties(dto, user);
return user;
}
}
配置规范
application.yml 模板
server:
port: ${SERVER_PORT:8080}
spring:
application:
name: ${spring.application.name}
datasource:
url: ${SPRING_DATASOURCE_URL:jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai}
username: ${SPRING_DATASOURCE_USERNAME:root}
password: ${SPRING_DATASOURCE_PASSWORD:}
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: validate # none/validate/update/create/create-drop
show-sql: false
open-in-view: false
redis:
host: ${SPRING_REDIS_HOST:localhost}
port: ${SPRING_REDIS_PORT:6379}
logging:
level:
root: INFO
${basePackage}: DEBUG
可迁移关键: 用环境变量覆盖默认值,不硬编码真实密码。
常用集成
Redis 缓存
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
return RedisCacheManager.builder(factory)
.cacheDefaults(RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(30))
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer())))
.build();
}
}
// 使用
@Service
public class UserService {
@Cacheable(value = "user", key = "#id")
public UserVO getById(Long id) { ... }
@CacheEvict(value = "user", key = "#id")
public void update(Long id, UserUpdateDTO dto) { ... }
}
定时任务
@Configuration
@EnableScheduling
public class ScheduleConfig {}
@Component
@Slf4j
public class ScheduledTasks {
@Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点
public void cleanExpiredData() {
log.info("Cleaning expired data...");
}
@Scheduled(fixedRate = 60000) // 每60秒
public void heartbeat() {
log.debug("Heartbeat check");
}
}
AOP 日志
@Aspect
@Component
@Slf4j
public class LogAspect {
@Around("execution(* ${basePackage}.controller..*(..))")
public Object logController(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long elapsed = System.currentTimeMillis() - start;
log.info("{}.{} -> {}ms",
joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), elapsed);
return result;
}
}
测试规范
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
void shouldReturnUserList() throws Exception {
when(userService.listUsers(anyInt(), anyInt(), any()))
.thenReturn(new PageResult<>(1, 1, 20, List.of()));
mockMvc.perform(get("/api/v1/users"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(200));
}
}
常用命令
# 启动(自动检测 profile) mvn spring-boot:run # 指定 profile mvn spring-boot:run -Dspring-boot.run.profiles=dev # 打包 mvn clean package -DskipTests # 运行 jar java -jar target/*.jar --server.port=8081 # 测试 mvn test mvn test -Dtest=UserControllerTest # 查看依赖树(定位版本冲突) mvn dependency:tree | grep -E "conflict|omitted" # 生成 OpenAPI 文档(springdoc) # 启动后访问: http://localhost:8080/swagger-ui.html
性能调优清单
| 项目 | 配置 | 说明 |
|---|---|---|
| 连接池 | spring.datasource.hikari.maximum-pool-size=20 |
默认10,生产可调20-50 |
| JPA | spring.jpa.open-in-view=false |
避免长连接持有数据库连接 |
| Tomcat 线程 | server.tomcat.threads.max=200 |
默认200 |
| 日志 | 生产关闭 show-sql |
避免 IO 瓶颈 |
| 缓存 | 热点数据加 Redis 缓存 | TTL 按业务设 |
| 异步 | @EnableAsync + @Async |
非核心路径异步化 |
| 压缩 | server.compression.enabled=true |
减少带宽 |
常见问题排查
启动失败
# 看完整堆栈(不要只看最后几行) mvn spring-boot:run 2>&1 | tee startup.log grep "Caused by:" startup.log
90% 的启动失败原因:
- 数据库连不上 → 检查
spring.datasource.url - 端口被占 →
lsof -i :8080或netstat -ano | findstr 8080 - Bean 冲突 →
@Primary或@Qualifier解决 - 循环依赖 → 重构为
@Lazy注入或用 setter 注入 - 版本不兼容 →
mvn dependency:tree查冲突
接口 404
- 检查
@RequestMapping路径拼写 - 检查包扫描范围:启动类
@SpringBootApplication是否在上层包 - 检查
context-path:server.servlet.context-path配置
事务不回滚
// ❌ 同一个类内部调用不走代理
public void methodA() {
this.methodB(); // @Transactional 不生效
}
// ✅ 注入自己或移到另一个 Service
@Service
public class OtherService {
@Transactional
public void methodB() { ... }
}
环境检测脚本
#!/bin/bash # check-env.sh — 在任何机器上检测 Spring Boot 开发环境 echo "Java: $(java -version 2>&1 | head -1)" echo "Maven: $(mvn -v 2>&1 | head -1)" echo "Gradle: $(gradle -v 2>&1 | head -1)" echo "Spring Boot project: $(grep -l 'spring-boot-starter' pom.xml build.gradle 2>/dev/null || echo 'NOT FOUND')" echo "Boot version: $(grep '' pom.xml 2>/dev/null | head -1 | sed 's/.* //;s/ //')" echo "Database: $(grep 'spring.datasource.url' src/main/resources/application*.yml 2>/dev/null | head -1)" echo "Port: $(grep 'server.port' src/main/resources/application*.yml 2>/dev/null | head -1)"
注意事项
- 本 skill 不绑定任何特定项目——所有路径都是相对路径
${basePackage}是占位符,使用时替换为项目实际根包名- 所有配置示例都通过了环境变量覆盖机制,不会泄露真实密码
- 代码示例遵循 Spring Boot 3.x + Java 17 标准
- 兼容 Maven 和 Gradle 两种构建工具
热门AI工具
相关专题
Spring Boot 是一个基于 Spring 框架的 Java 开发框架,它通过 约定优于配置的原则,大幅简化了 Spring 应用的初始搭建、配置和开发过程,让开发者可以快速构建独立的、生产级别的 Spring 应用,无需繁琐的样板配置,通常集成嵌入式服务器(如 Tomcat),提供“开箱即用”的体验,是构建微服务和 Web 应用的流行工具。
356
2025.12.22
j2ee和spring boot的主要区别在于架构和易用性。j2ee采用复杂的分层架构,而spring boot采用单体架构并集成所有组件,简化了部署。spring boot以其开箱即用性和丰富的自动化功能而著称,而j2ee的配置过程更为繁琐。想了解更多j2ee的相关内容,可以阅读本专题下面的文章。
4003
2024.04.16
SpringBoot项目搭建的步骤:1、确保JDK、Maven、IDE等工具已安装;2、使用Maven创建一个新的Spring Boot项目;3、在Spring Boot项目中,可以通过添加依赖来引入所需的功能模块;4、编写一个Spring Boot应用程序;5、运行Spring Boot项目;6、在完成开发和测试后,将Spring Boot项目部署到生产环境。详细内容,请阅读本专题的下面文章。
1663
2023.09.08
本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。
0
2026.11.12
本专题围绕Go-Zero的安装与工具链配置展开,讲清Go版本要求、goctl安装方式、代理镜像、protoc依赖与环境变量设置,说明多版本共存、升级回退与CI流水线安装的做法,并整理安装阶段的常见报错与验证步骤。
0
2026.11.12
本专题整理Go-Zero的入门知识,从框架定位、环境准备到跑通第一个API服务,讲清目录分层、配置加载、日志与中间件的基本用法,并对比Gin、Kratos的差异,帮助Go开发者建立整体认知,判断它是否适合当前项目。
0
2026.11.12
本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。
0
2026.11.06
围绕Postman HTTP请求头配置展开,讲解Headers选项的具体使用方式,包括Key和Value参数填写、请求头信息添加、常见Header字段设置及请求头修改方法,帮助用户解决接口调试过程中遇到的请求头配置问题。
0
2026.11.06
详细介绍Postman接口请求的创建与发送方法,涵盖GET和POST请求、URL配置、请求参数、Headers请求头、Body请求体设置以及响应结果查看,帮助用户掌握Postman接口请求的完整操作流程。
0
2026.11.06
热门下载
相关下载
精品课程
共47课时 | 7.5万人学习
最新文章