讲师中心 微信公众号

工具推荐

视频效率加速
剧云
剧云

中文短剧剧本制作平台

立刻MV
立刻MV

低成本歌曲 MV、视频生成

Laper
Laper

剧本策划到成片协作

AniShort
AniShort

AI短剧协同制作平台

springboot项目制作专家

Polar Sponsor
爱发电 赞助
.NET 9.0

通用的 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% 的启动失败原因:

  1. 数据库连不上 → 检查 spring.datasource.url
  2. 端口被占 → lsof -i :8080 或 netstat -ano | findstr 8080
  3. Bean 冲突 → @Primary 或 @Qualifier 解决
  4. 循环依赖 → 重构为 @Lazy 注入或用 setter 注入
  5. 版本不兼容 → mvn dependency:tree 查冲突

接口 404

  1. 检查 @RequestMapping 路径拼写
  2. 检查包扫描范围:启动类 @SpringBootApplication 是否在上层包
  3. 检查 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)"

注意事项

  1. 本 skill 不绑定任何特定项目——所有路径都是相对路径
  2. ${basePackage} 是占位符,使用时替换为项目实际根包名
  3. 所有配置示例都通过了环境变量覆盖机制,不会泄露真实密码
  4. 代码示例遵循 Spring Boot 3.x + Java 17 标准
  5. 兼容 Maven 和 Gradle 两种构建工具
目录

热门AI工具

更多
DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

讯飞智文

一款面向学习和办公场景的AI文档创作工具,可辅助生成PPT与Word文档,提高资料整理和内容制作效率。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

花生AI
花生AI Hot

一款AI视频创作工具,主要用于B站推出的AI视频创作工具,适合需要提升相关任务效率的用户。

相关专题

更多
Java Spring Boot 4更新教程_Java Spring Boot 4有哪些新特性
Java Spring Boot 4更新教程_Java Spring Boot 4有哪些新特性

Spring Boot 是一个基于 Spring 框架的 Java 开发框架,它通过 约定优于配置的原则,大幅简化了 Spring 应用的初始搭建、配置和开发过程,让开发者可以快速构建独立的、生产级别的 Spring 应用,无需繁琐的样板配置,通常集成嵌入式服务器(如 Tomcat),提供“开箱即用”的体验,是构建微服务和 Web 应用的流行工具。

356

2025.12.22

j2ee和springboot的区别是什么
j2ee和springboot的区别是什么

j2ee和spring boot的主要区别在于架构和易用性。j2ee采用复杂的分层架构,而spring boot采用单体架构并集成所有组件,简化了部署。spring boot以其开箱即用性和丰富的自动化功能而著称,而j2ee的配置过程更为繁琐。想了解更多j2ee的相关内容,可以阅读本专题下面的文章。

4003

2024.04.16

SpringBoot项目搭建步骤
SpringBoot项目搭建步骤

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开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

0

2026.11.12

Go-Zero安装与goctl环境配置教程
Go-Zero安装与goctl环境配置教程

本专题围绕Go-Zero的安装与工具链配置展开,讲清Go版本要求、goctl安装方式、代理镜像、protoc依赖与环境变量设置,说明多版本共存、升级回退与CI流水线安装的做法,并整理安装阶段的常见报错与验证步骤。

0

2026.11.12

Go-Zero零基础入门教程
Go-Zero零基础入门教程

本专题整理Go-Zero的入门知识,从框架定位、环境准备到跑通第一个API服务,讲清目录分层、配置加载、日志与中间件的基本用法,并对比Gin、Kratos的差异,帮助Go开发者建立整体认知,判断它是否适合当前项目。

0

2026.11.12

Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

0

2026.11.06

Postman请求头Headers怎么设置
Postman请求头Headers怎么设置

围绕Postman HTTP请求头配置展开,讲解Headers选项的具体使用方式,包括Key和Value参数填写、请求头信息添加、常见Header字段设置及请求头修改方法,帮助用户解决接口调试过程中遇到的请求头配置问题。

0

2026.11.06

Postman接口请求发送教程
Postman接口请求发送教程

详细介绍Postman接口请求的创建与发送方法,涵盖GET和POST请求、URL配置、请求参数、Headers请求头、Body请求体设置以及响应结果查看,帮助用户掌握Postman接口请求的完整操作流程。

0

2026.11.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Redis6入门到精通超详细教程
Redis6入门到精通超详细教程

共47课时 | 7.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn