spring-boot-engineer by jeffallan/claude-skills
npx skills add https://github.com/jeffallan/claude-skills --skill spring-boot-engineer./mvnw test(或 ./gradlew test)并在继续前确认全部通过。如果测试失败:检查堆栈跟踪,定位失败的断言或组件,修复问题,并重新运行完整的测试套件/actuator/health 返回 UP。如果健康状态为 DOWN:检查响应中的 components 详情,解决故障组件(例如,数据源、消息代理),并重新验证根据上下文加载详细指导:
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 主题 | 参考 | 加载时机 |
|---|---|---|
| Web 层 | references/web.md | 控制器、REST API、验证、异常处理 |
| 数据访问 | references/data.md | Spring Data JPA、存储库、事务、投影 |
| 安全性 | references/security.md | Spring Security 6、OAuth2、JWT、方法安全 |
| 云原生 | references/cloud.md | Spring Cloud、配置、服务发现、网关、弹性 |
| 测试 | 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);
}
}
@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);
}
}
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") 绑定到记录类/类 |
| 使用恰当的注解 | 业务逻辑用 @Service,数据访问用 @Repository,HTTP 用 @RestController |
| 事务范围 | 多步骤写入操作使用 @Transactional;读取操作使用 @Transactional(readOnly = true) |
| 隐藏内部细节 | 在 @RestControllerAdvice 中捕获领域异常;返回问题详情,而非堆栈跟踪 |
| 外部化密钥 | 使用环境变量或 Spring Cloud Config — 切勿使用 application.properties |
@Autowired)@Service/@Repository/@Controller 时使用 @Component.block())application.properties/application.yml 中存储密钥或凭据WebSecurityConfigurerAdapter)每周安装量
2.5K
仓库
GitHub 星标
7.3K
首次出现
2026年1月20日
安全审计
安装于
claude-code2.1K
opencode1.1K
gemini-cli1.0K
codex1.0K
github-copilot968
cursor893
./mvnw test (or ./gradlew test) and confirm all pass before proceeding. If tests fail: review the stack trace, isolate the failing assertion or component, fix the issue, and re-run the full suite/actuator/health returns UP. If health is DOWN: check the components detail in the response, resolve the failing component (e.g., datasource, broker), and re-validateLoad detailed guidance based on context:
| Topic | Reference | Load When |
|---|---|---|
| Web Layer | references/web.md | Controllers, REST APIs, validation, exception handling |
| Data Access | references/data.md | Spring Data JPA, repositories, transactions, projections |
| Security | references/security.md | Spring Security 6, OAuth2, JWT, method security |
| Cloud Native | references/cloud.md | Spring Cloud, Config, Discovery, Gateway, resilience |
| Testing | references/testing.md |
A standard Spring Boot feature consists of these layers. Use these as copy-paste starting points.
@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);
}
}
@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);
}
}
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"));
}
}
| Rule | Correct Pattern |
|---|---|
| Constructor injection | public MyService(Dep dep) { this.dep = dep; } |
| Validate API input | @Valid @RequestBody MyRequest req on every mutating endpoint |
| Type-safe config | @ConfigurationProperties(prefix = "app") bound to a record/class |
| Appropriate stereotype | @Service for business logic, @Repository for data, @RestController for HTTP |
| Transaction scope |
@Autowired on fields)@Component when @Service/@Repository/@Controller applies.block() inside a WebFlux chain)application.properties/application.ymlWebSecurityConfigurerAdapter)Weekly Installs
2.5K
Repository
GitHub Stars
7.3K
First Seen
Jan 20, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
claude-code2.1K
opencode1.1K
gemini-cli1.0K
codex1.0K
github-copilot968
cursor893
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
102,200 周安装
AI智能体长期记忆系统 - 精英级架构,融合6种方法,永不丢失上下文
1,200 周安装
AI新闻播客制作技能:实时新闻转对话式播客脚本与音频生成
1,200 周安装
Word文档处理器:DOCX创建、编辑、分析与修订痕迹处理全指南 | 自动化办公解决方案
1,200 周安装
React Router 框架模式指南:全栈开发、文件路由、数据加载与渲染策略
1,200 周安装
Nano Banana AI 图像生成工具:使用 Gemini 3 Pro 生成与编辑高分辨率图像
1,200 周安装
SVG Logo Designer - AI 驱动的专业矢量标识设计工具,生成可缩放品牌标识
1,200 周安装
| @SpringBootTest, MockMvc, Testcontainers, test slices |
@Transactional on multi-step writes; @Transactional(readOnly = true) on reads |
| Hide internals | Catch domain exceptions in @RestControllerAdvice; return problem details, not stack traces |
| Externalize secrets | Use environment variables or Spring Cloud Config — never application.properties |