mcpField
S
spring-boot-rest-api-standards

spring-boot-rest-api-standards

github.com/giuseppe-trisciuoglio开发3654.2k 次安装7 周前更新
代码仓库

关于 spring-boot-rest-api-standards

面向 Spring Boot 开发者的 REST API 设计规范技能,涵盖端点、DTO、校验、错误处理、分页与安全头配置。适用于新建或审查 API。

主要功能

  1. 01资源式 URL 与 HTTP 方法规范
  2. 02状态码及错误响应设计
  3. 03DTO 与 Jakarta 校验
  4. 04分页、过滤与安全头配置

适用场景

  1. 01创建 REST 端点和 API 路由
  2. 02设计 DTO 与 API 契约
  3. 03实现统一异常处理和输入校验
  4. 04审查 REST API 架构

安装

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

$npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill spring-boot-rest-api-standards

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

包含的文件

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

references/
architecture-patterns.md
examples.md
http-reference.md
pagination-and-filtering.md
references.md
security-headers.md
spring-web-annotations.md

详细介绍

Spring Boot REST API 标准

概述

适用于 Spring Boot 的 REST API 设计标准,涵盖 URL 设计、HTTP 方法、状态码、DTO、验证、错误处理、分页和安全标头。

适用场景

  • 创建 REST 端点和 API 路由
  • 设计 DTO 和 API 契约
  • 实现错误处理和验证
  • 设置分页和筛选
  • 配置安全标头和 CORS
  • 审查 REST API 架构

说明

构建 RESTful API 端点

按照以下步骤创建设计良好的 REST API 端点:

  1. 设计基于资源的 URL

    • 使用复数名词作为资源名称
    • 遵循 REST 约定:GET /users、POST /users、PUT /users/{id}
    • 避免使用基于操作的 URL,例如 /getUserList
  2. 使用恰当的 HTTP 方法

    • GET:检索资源(安全、幂等)
    • POST:创建资源(非幂等)
    • PUT:替换整个资源(幂等)
    • PATCH:部分更新(非幂等)
    • DELETE:删除资源(幂等)
  3. 使用恰当的状态码

    • 200 OK:GET/PUT/PATCH 请求成功
    • 201 Created:POST 请求成功,并带有 Location 标头
    • 204 No Content:DELETE 请求成功
    • 400 Bad Request:请求数据无效
    • 404 Not Found:资源不存在
    • 409 Conflict:资源重复
    • 500 Internal Server Error:发生意外错误
  4. 创建请求/响应 DTO

    • 将 API 契约与领域实体分离
    • 使用 Java record 或 Lombok @Data/@Value
    • 应用 Jakarta 验证注解
    • 尽可能让 DTO 保持不可变
  5. 实现验证

    • 在 @RequestBody 参数上使用 @Valid 注解
    • 应用验证约束(@NotBlank、@Email、@Size 等)
    • 使用 MethodArgumentNotValidException 处理验证错误
  6. 设置错误处理

    • 使用 @RestControllerAdvice 进行全局异常处理
    • 返回包含状态、错误、消息和时间戳的标准化错误响应
    • 对特定 HTTP 状态码使用 ResponseStatusException
  7. 配置分页

    • 对大型数据集使用 Pageable
    • 包含 page、size、sort 参数
    • 返回包含 total elements、totalPages 等信息的元数据
  8. 添加安全标头

    • 配置 CORS 策略
    • 设置内容安全策略
    • 包含 X-Frame-Options、X-Content-Type-Options

验证检查点:

  • 步骤 1-2 后:确认 URL 结构遵循 REST 约定(使用 /users,而非 /getUsers)
  • 步骤 3 后:测试每个端点是否返回正确的状态码
  • 步骤 4-5 后:在继续操作前,使用 curl 或 HTTPie 验证 DTO
  • 步骤 6 后:确认错误响应符合标准格式

示例

基本 CRUD 控制器
@RestController
@RequestMapping("/v1/users")
@RequiredArgsConstructor
@Slf4j
public class UserController {
    private final UserService userService;

    @GetMapping
    public ResponseEntity<Page<UserResponse>> getAllUsers(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int pageSize) {
        log.debug("Fetching users page {} size {}", page, pageSize);
        Page<UserResponse> users = userService.getAll(page, pageSize);
        return ResponseEntity.ok(users);
    }

    @GetMapping("/{id}")
    public ResponseEntity<UserResponse> getUserById(@PathVariable Long id) {
        return ResponseEntity.ok(userService.getById(id));
    }

    @PostMapping
    public ResponseEntity<UserResponse> createUser(@Valid @RequestBody CreateUserRequest request) {
        UserResponse created = userService.create(request);
        return ResponseEntity.status(HttpStatus.CREATED).body(created);
    }

    @PutMapping("/{id}")
    public ResponseEntity<UserResponse> updateUser(
            @PathVariable Long id,
            @Valid @RequestBody UpdateUserRequest request) {
        return ResponseEntity.ok(userService.update(id, request));
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        userService.delete(id);
        return ResponseEntity.noContent().build();
    }
}
请求/响应 DTO
// Request DTO
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CreateUserRequest {
    @NotBlank(message = "User name cannot be blank")
    private String name;

    @Email(message = "Valid email required")
    private String email;
}

// Response DTO
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserResponse {
    private Long id;
    private String name;
    private String email;
    private LocalDateTime createdAt;
}
全局异常处理器
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleValidationException(
            MethodArgumentNotValidException ex, WebRequest request) {
        String errors = ex.getBindingResult().getFieldErrors().stream()
                .map(f -> f.getField() + ": " + f.getDefaultMessage())
                .collect(Collectors.joining(", "));

        ErrorResponse errorResponse = new ErrorResponse(
                HttpStatus.BAD_REQUEST.value(),
                "Validation Error",
                "Validation failed: " + errors,
                request.getDescription(false).replaceFirst("uri=", "")
        );
        return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(ResponseStatusException.class)
    public ResponseEntity<ErrorResponse> handleResponseStatusException(
            ResponseStatusException ex, WebRequest request) {
        ErrorResponse error = new ErrorResponse(
            ex.getStatusCode().value(),
            ex.getStatusCode().toString(),
            ex.getReason(),
            request.getDescription(false).replaceFirst("uri=", "")
        );
        return new ResponseEntity<>(error, ex.getStatusCode());
    }
}

最佳实践

1. 使用构造函数注入
@Service
@RequiredArgsConstructor
public class UserService {
    private final UserRepository userRepository;
}
2. 优先使用不可变 DTO(Java Records 或 @Value)
public record UserResponse(Long id, String name, String email) {}
3. 实现恰当的事务管理
@Service
@Transactional
public class UserService {
    @Transactional(readOnly = true)
    public Optional<User> findById(Long id) { return userRepository.findById(id); }

    @Transactional
    public User create(User user) { return userRepository.save(user); }
}

约束和警告

  1. 切勿直接暴露实体——使用 DTO 将 API 契约与领域模型分离
  2. 遵循 REST 约定——资源使用名词(/users),使用正确的 HTTP 方法、复数名称和恰当的状态码
  3. 全局处理所有异常——使用 @RestControllerAdvice,绝不让原始异常向外传播
  4. 始终对大型结果集进行分页——避免性能问题和 DDoS 漏洞
  5. 验证所有输入数据——在请求 DTO 上使用 Jakarta 验证注解
  6. 切勿暴露敏感数据——不要记录或暴露密码、令牌、个人身份信息

参考资料

  • 查看 references/ 目录,获取全面的参考资料,包括 HTTP 状态码、Spring 注解和详细示例
  • 参考 developer-kit-java:spring-boot-code-review-expert Agent,了解代码审查指南
  • 查看 spring-boot-dependency-injection/SKILL.md,了解依赖注入模式
  • 查看 ../spring-boot-test-patterns/SKILL.md,了解 REST API 测试方法

评论

支持 Markdown