mcpField
S
spring-boot-engineer

spring-boot-engineer

github.com/jeffallan开发12.1k8.5k 次安装今天更新
代码仓库

关于 spring-boot-engineer

面向构建生产级 Java 服务的 Spring Boot 工程技能,涵盖架构设计、实现、安全、测试与部署,并提供专题参考和起步代码结构。

主要功能

  1. 01需求与架构规划
  2. 02分层 Spring Boot 实现指导
  3. 03安全与输入验证实践
  4. 04单元、集成及切片测试
  5. 05Actuator 健康检查指导

适用场景

  1. 01规划 REST 服务边界与 API
  2. 02实现经过验证的 Spring Boot 端点
  3. 03排查测试或安全规则失败
  4. 04部署前检查服务健康状态

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jeffallan/claude-skills --skill spring-boot-engineer

安装后在 Claude Code 中输入/spring-boot-engineer确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
cloud.md
data.md
security.md
testing.md
web.md

详细介绍

Spring Boot 工程师

核心工作流

  1. 分析需求 — 确定服务边界、API、数据模型和安全需求
  2. 设计架构 — 规划微服务、数据访问、云集成和安全;编码前确认设计
  3. 实施 — 使用构造函数注入和分层架构创建服务(参见下方的快速入门)
  4. 保障安全 — 添加 Spring Security、OAuth2、方法安全和 CORS 配置;确认安全规则能够编译并通过测试。如果编译或测试失败:检查错误输出,修复失败的规则或配置,然后重新运行再继续
  5. 测试 — 编写单元、集成和切片测试;运行 ./mvnw test(或 ./gradlew test),并确认全部通过后再继续。如果测试失败:检查堆栈跟踪,定位失败的断言或组件,修复问题,然后重新运行完整测试套件
  6. 部署 — 通过 Actuator 配置健康检查和可观测性;验证 /actuator/health 返回 UP。如果健康状态为 DOWN:检查响应中的 components 详情,解决故障组件(例如数据源、消息代理),然后重新验证

参考指南

根据上下文加载详细指南:

主题参考资料加载时机
Web 层references/web.md控制器、REST API、验证、异常处理
数据访问references/data.mdSpring Data JPA、仓库、事务、投影
安全references/security.mdSpring Security 6、OAuth2、JWT、方法安全
云原生references/cloud.mdSpring Cloud、Config、Discovery、Gateway、弹性
测试references/testing.md@SpringBootTest、MockMvc、Testcontainers、测试切片

快速入门 — 最小可用结构

标准的 Spring Boot 功能由以下层组成。可将这些示例用作复制粘贴的起点。

实体
@Entity
@Table(name = "products")
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank
    private String name;

    @DecimalMin("0.0")
    private BigDecimal price;

    // getters / setters or use @Data (Lombok)
}
仓库
public interface ProductRepository extends JpaRepository<Product, Long> {
    List<Product> findByNameContainingIgnoreCase(String name);
}
服务(构造函数注入)
@Service
public class ProductService {
    private final ProductRepository repo;

    public ProductService(ProductRepository repo) { // constructor injection — no @Autowired
        this.repo = repo;
    }

    @Transactional(readOnly = true)
    public List<Product> search(String name) {
        return repo.findByNameContainingIgnoreCase(name);
    }

    @Transactional
    public Product create(ProductRequest request) {
        var product = new Product();
        product.setName(request.name());
        product.setPrice(request.price());
        return repo.save(product);
    }
}
REST 控制器
@RestController
@RequestMapping("/api/v1/products")
@Validated
public class ProductController {
    private final ProductService service;

    public ProductController(ProductService service) {
        this.service = service;
    }

    @GetMapping
    public List<Product> search(@RequestParam(defaultValue = "") String name) {
        return service.search(name);
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public Product create(@Valid @RequestBody ProductRequest request) {
        return service.create(request);
    }
}
DTO(record)
public record ProductRequest(
    @NotBlank String name,
    @DecimalMin("0.0") BigDecimal price
) {}
全局异常处理器
@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Map<String, String> handleValidation(MethodArgumentNotValidException ex) {
        return ex.getBindingResult().getFieldErrors().stream()
            .collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
    }

    @ExceptionHandler(EntityNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public Map<String, String> handleNotFound(EntityNotFoundException ex) {
        return Map.of("error", ex.getMessage());
    }
}
测试切片
@WebMvcTest(ProductController.class)
class ProductControllerTest {
    @Autowired MockMvc mockMvc;
    @MockBean ProductService service;

    @Test
    void createProduct_validRequest_returns201() throws Exception {
        var product = new Product(); product.setName("Widget"); product.setPrice(BigDecimal.TEN);
        when(service.create(any())).thenReturn(product);

        mockMvc.perform(post("/api/v1/products")
                .contentType(MediaType.APPLICATION_JSON)
                .content("""{"name":"Widget","price":10.0}"""))
            .andExpect(status().isCreated())
            .andExpect(jsonPath("$.name").value("Widget"));
    }
}

约束

必须执行
规则正确模式
构造函数注入public MyService(Dep dep) { this.dep = dep; }
验证 API 输入在每个有修改操作的端点上使用 @Valid @RequestBody MyRequest req
类型安全的配置将 @ConfigurationProperties(prefix = "app") 绑定到 record/class
使用合适的构造型注解业务逻辑使用 @Service,数据访问使用 @Repository,HTTP 使用 @RestController
事务范围多步写入使用 @Transactional;读取操作使用 @Transactional(readOnly = true)
隐藏内部细节在 @RestControllerAdvice 中捕获领域异常;返回问题详情,而非堆栈跟踪
将密钥外置使用环境变量或 Spring Cloud Config;绝不放在 application.properties 中
不得执行
  • 使用字段注入(在字段上使用 @Autowired)
  • 跳过 API 端点的输入验证
  • 在适用 @Service/@Repository/@Controller 时使用 @Component
  • 混用阻塞式和响应式代码(例如,在 WebFlux 链中调用 .block())
  • 将密钥或凭据存储在 application.properties/application.yml 中
  • 硬编码 URL、凭据或特定环境的值
  • 使用已弃用的 Spring Boot 2.x 模式(例如 WebSecurityConfigurerAdapter)

由 @jeffallan 维护;他是 Synergetic Solutions 的首席顾问。

文档

评论

支持 Markdown