api-development

SKILL.md

API 接口设计规范

核心规范

原则 说明
RESTful 风格 使用标准 HTTP 方法表达语义
认证保护 所有业务接口必须添加认证注解
参数校验 使用分组校验区分新增/修改场景
统一响应 使用统一的响应格式包装返回数据

HTTP 方法规范

操作 方法 路径示例
列表查询 GET /list/page
获取详情 GET /{id}
新增 POST //add
修改 PUT //update
删除 DELETE /{ids}
导出 POST /export
导入 POST /import

Controller 标准模板

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/[模块]/[功能]")
public class XxxController {

    private final XxxService xxxService;

    /**
     * 分页查询
     */
    @GetMapping("/page")
    public Result<PageResult<XxxVO>> page(XxxQueryDTO query) {
        return Result.ok(xxxService.pageList(query));
    }

    /**
     * 获取详情
     */
    @GetMapping("/{id}")
    public Result<XxxVO> getById(@PathVariable Long id) {
        return Result.ok(xxxService.getById(id));
    }

    /**
     * 新增
     */
    @PostMapping
    public Result<Long> add(@Validated(InsertGroup.class) @RequestBody XxxDTO dto) {
        return Result.ok(xxxService.add(dto));
    }

    /**
     * 修改
     */
    @PutMapping
    public Result<Void> update(@Validated(UpdateGroup.class) @RequestBody XxxDTO dto) {
        xxxService.update(dto);
        return Result.ok();
    }

    /**
     * 删除
     */
    @DeleteMapping("/{ids}")
    public Result<Void> delete(@PathVariable List<Long> ids) {
        xxxService.deleteByIds(ids);
        return Result.ok();
    }
}

统一响应封装

Result 包装类(通用模式)

@Data
public class Result<T> {
    private int code;
    private String message;
    private T data;

    public static <T> Result<T> ok() {
        return ok(null);
    }

    public static <T> Result<T> ok(T data) {
        Result<T> result = new Result<>();
        result.setCode(200);
        result.setMessage("success");
        result.setData(data);
        return result;
    }

    public static <T> Result<T> fail(String message) {
        Result<T> result = new Result<>();
        result.setCode(500);
        result.setMessage(message);
        return result;
    }
}

分页响应

@Data
public class PageResult<T> {
    private List<T> records;
    private long total;
    private long current;
    private long size;
}

参数校验

分组校验

// DTO 中使用分组
@Data
public class XxxDTO {
    @NotNull(message = "ID不能为空", groups = {UpdateGroup.class})
    private Long id;

    @NotBlank(message = "名称不能为空", groups = {InsertGroup.class, UpdateGroup.class})
    @Size(max = 100, message = "名称长度不能超过100个字符")
    private String name;

    @Min(value = 0, message = "排序不能为负数")
    private Integer sort;
}

// Controller 中应用
@PostMapping
public Result<Long> add(@Validated(InsertGroup.class) @RequestBody XxxDTO dto) { ... }

@PutMapping
public Result<Void> update(@Validated(UpdateGroup.class) @RequestBody XxxDTO dto) { ... }

Jakarta Validation: JDK 17+ 必须 import jakarta.validation.constraints.*

查询参数

@Data
public class XxxQueryDTO {
    private String keyword;
    private Integer status;

    @Min(value = 1)
    private Integer pageNum = 1;

    @Min(value = 1) @Max(value = 100)
    private Integer pageSize = 10;
}

常见场景

带分布式锁的导入

@PostMapping("/import")
public Result<Void> importExcel(@RequestPart("file") MultipartFile file) {
    if (file == null || file.isEmpty()) {
        throw new [你的异常类]("文件不能为空");
    }
    RLock lock = redissonClient.getLock("import:lock:" + getCurrentTenantId());
    try {
        if (!lock.tryLock(5, 60, TimeUnit.SECONDS)) {
            throw new [你的异常类]("正在处理中,请稍后再试");
        }
        try {
            xxxService.importExcel(file);
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        throw new [你的异常类]("导入被中断");
    }
    return Result.ok();
}

批量删除

@DeleteMapping("/{ids}")
public Result<Void> delete(@PathVariable List<Long> ids) {
    if (ids == null || ids.isEmpty()) {
        throw new [你的异常类]("ID列表不能为空");
    }
    xxxService.deleteByIds(ids);
    return Result.ok();
}

文件上传

@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Result<UploadResult> upload(@RequestPart("file") MultipartFile file) {
    return Result.ok(ossService.upload(file));
}

API 文档注解

Swagger / SpringDoc 注解

// SpringDoc (OpenAPI 3.0, 推荐)
@Tag(name = "用户管理")                              // Controller 类
@Operation(summary = "新增用户")                      // 方法
@Schema(description = "用户DTO")                      // DTO/VO 类
@Schema(description = "主键ID", requiredMode = REQUIRED) // 字段

// Swagger 2 (旧项目)
@Api(value = "用户管理", tags = "用户管理")
@ApiOperation(value = "新增用户")
@ApiModel("用户DTO")
@ApiModelProperty(value = "主键ID", required = true)

全局异常处理

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler([你的异常类].class)
    public Result<Void> handleBusinessException([你的异常类] e) {
        return Result.fail(e.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<Void> handleValidException(MethodArgumentNotValidException e) {
        String message = e.getBindingResult().getFieldErrors().stream()
            .map(FieldError::getDefaultMessage)
            .collect(Collectors.joining(", "));
        return Result.fail(message);
    }

    @ExceptionHandler(Exception.class)
    public Result<Void> handleException(Exception e) {
        log.error("系统异常", e);
        return Result.fail("系统繁忙,请稍后再试");
    }
}

检查清单

  • 认证注解(@PreAuthorize / [你的认证注解]
  • API 文档注解(@Operation / @ApiOperation
  • 参数校验 @Validated + 分组
  • 统一响应包装 Result<T>
  • 敏感操作加分布式锁
  • 全局异常处理器已配置

相关技能

需要了解 Skill
异常处理 error-handler
数据库设计 database-ops
缓存 redis-cache
文件上传 file-oss-management
Weekly Installs
4
GitHub Stars
9
First Seen
9 days ago
Installed on
gemini-cli4
github-copilot4
codex4
kimi-cli4
cursor4
amp4