askill
java-api-endpoint

java-api-endpointSafety 70Repository

Add RESTful API endpoints to Spring Boot projects following layered architecture conventions. Covers Controller, Facade patterns, pagination, batch operations, and OpenAPI annotations. Use when adding API endpoints, creating REST interfaces, or implementing query/mutation operations.

0 stars
1.2k downloads
Updated 2/14/2026

Package Files

Loading files...
SKILL.md

API 端点开发

在 Spring Boot 分层架构项目中添加 RESTful API 端点。

前置: 遵守 java-architecture-guide 中的分层原则。

RESTful 规范

路径格式

/api/v{version}/{resources}
  • 资源名: 复数名词, kebab-case
  • 示例: /api/v1/alert-policies, /api/v1/video-sources

标准 CRUD 映射

操作方法路径返回
创建POST/api/v1/policiesApiResponse<IdResp>
更新PUT/api/v1/policies/{id}ApiResponse<Void>
删除DELETE/api/v1/policies/{id}ApiResponse<Void>
详情GET/api/v1/policies/{id}ApiResponse<DetailDTO>
分页列表GET/api/v1/policies?page=1&size=20ApiResponse<PageResult<Card>>
游标分页GET/api/v1/policies/stream?cursor=&size=20ApiResponse<CursorPageResult<Card>>
批量操作POST/api/v1/policies/batch/{action}ApiResponse<BatchResp>

Controller 模式

类声明

@Slf4j
@RestController
@RequestMapping(path = "/api/v1/policies", produces = MediaType.APPLICATION_JSON_VALUE)
@Tag(name = "预警策略", description = "预警策略管理接口")
@RequiredArgsConstructor
public class PolicyController {
    private final PolicyFacade facade;  // 只注入 Facade
}

必需注解:

  • @Tag(name, description) — OpenAPI 分组
  • @RequestMapping(path, produces=JSON) — 统一 JSON 响应
  • @RequiredArgsConstructor — 构造器注入

统一响应

所有方法返回 ApiResponse<T>:

ApiResponse.ok()              // 无数据成功
ApiResponse.ok(data)          // 带数据成功
ApiResponse.error(code, msg)  // 错误

参数校验

// Request Body 校验
@PostMapping
public ApiResponse<IdResp> create(@Valid @RequestBody PolicyCreateReq req)

// Path Variable 校验 (类上需加 @Validated)
@Validated
@RestController
public class PolicyController {
    @DeleteMapping("/{id}")
    public ApiResponse<Void> delete(
        @NotNull(message = "ID不能为空")
        @Positive(message = "ID必须为正数")
        @PathVariable Long id)
}

5 种端点模板

1. 分页查询 (偏移分页)

适用于小数据量,前端需要页码跳转。

@Operation(summary = "分页查询策略列表")
@GetMapping
public ApiResponse<PageResult<PolicyCard>> getPage(
        @Parameter(description = "页码", example = "1")
        @RequestParam(defaultValue = "1") int page,
        @Parameter(description = "每页大小", example = "20")
        @RequestParam(defaultValue = "20") int size,
        @Parameter(description = "策略名称")
        @RequestParam(required = false) String name,
        @Parameter(description = "状态")
        @RequestParam(required = false) String status) {
    return ApiResponse.ok(facade.getPage(page, size, name, status));
}

2. 游标分页 (大数据量)

适用于大数据量,避免深分页性能问题。

@Operation(summary = "游标分页查询")
@GetMapping("/stream")
public ApiResponse<CursorPageResult<PolicyCard>> getStreamPage(
        @Parameter(description = "游标(上页最后一条ID)")
        @RequestParam(required = false) Long cursor,
        @Parameter(description = "每页大小")
        @RequestParam(defaultValue = "20") int size,
        @Parameter(description = "策略名称")
        @RequestParam(required = false) String name) {
    if (cursor != null && cursor < 0L) {
        cursor = null;
    }
    return ApiResponse.ok(facade.getStreamPage(cursor, size, name));
}

Service 层游标分页实现要点:

LambdaQueryWrapper<Entity> wrapper = new LambdaQueryWrapper<>();
if (cursor != null) {
    wrapper.lt(Entity::getId, cursor);  // ID < cursor
}
wrapper.orderByDesc(Entity::getId)
       .last("LIMIT " + (size + 1));   // 多查一条判断 hasMore

List<Entity> list = mapper.selectList(wrapper);
boolean hasMore = list.size() > size;
if (hasMore) list = list.subList(0, size);

3. 详情查询

@Operation(summary = "查询策略详情")
@GetMapping("/{id}")
public ApiResponse<PolicyDetail> getDetail(
        @Parameter(description = "策略ID", example = "1")
        @PathVariable Long id) {
    return ApiResponse.ok(facade.getDetail(id));
}

4. 创建 / 更新 / 删除

@Operation(summary = "创建策略")
@PostMapping
public ApiResponse<IdResp> create(@Valid @RequestBody PolicyCreateReq req) {
    Long id = facade.create(req);
    return ApiResponse.ok(new IdResp(id));
}

@Operation(summary = "更新策略")
@PutMapping("/{id}")
public ApiResponse<Void> update(
        @Parameter(description = "策略ID") @PathVariable Long id,
        @Valid @RequestBody PolicyUpdateReq req) {
    facade.update(id, req);
    return ApiResponse.ok();
}

@Operation(summary = "删除策略")
@DeleteMapping("/{id}")
public ApiResponse<Void> delete(
        @Parameter(description = "策略ID") @PathVariable Long id) {
    facade.delete(id);
    return ApiResponse.ok();
}

5. 批量操作

@Operation(summary = "批量启动任务")
@PostMapping("/batch/start")
public ApiResponse<TaskBatchResp> batchStart(
        @Valid @RequestBody TaskBatchReq req) {
    return ApiResponse.ok(facade.batchStart(req));
}

Facade 层批量操作模式 (部分成功):

public TaskBatchResp batchStart(TaskBatchReq req) {
    TaskBatchResp resp = new TaskBatchResp();
    for (Long taskId : req.getTaskIds()) {
        try {
            startTask(taskId);
            resp.addSuccess(taskId);
        } catch (Exception e) {
            resp.addFailure(taskId, e.getMessage());
        }
    }
    return resp;
}

Facade 编排模式

写操作: 验证 → 执行 → 返回

@Transactional(rollbackFor = Exception.class)
public Long create(PolicyCreateReq req) {
    // 1. 验证关联数据有效性
    validateRelatedData(req);
    // 2. 调用 Service 执行
    Long id = policyService.create(req);
    // 3. 创建关联数据
    createTimePlans(id, req.getTimePlans());
    return id;
}

读操作: 查询 → 批量关联 → 丰富结果

public PageResult<PolicyCard> getPage(int page, int size, String name, String status) {
    // 1. 查询主数据
    PageResult<PolicyCard> result = policyService.getPage(page, size, name, status);
    // 2. 提取 ID 批量查询关联数据
    List<Long> policyIds = result.getRecords().stream()
            .map(PolicyCard::getId).toList();
    Map<Long, List<TimePlan>> planMap = timePlanService.batchGetByPolicyIds(policyIds);
    // 3. 丰富结果
    result.getRecords().forEach(card ->
            card.setTimePlans(planMap.getOrDefault(card.getId(), List.of())));
    return result;
}

OpenAPI 注解速查

注解位置用途
@Tag(name, description)Controller 类API 分组
@Operation(summary, description)方法操作说明
@Parameter(description, example)参数参数说明
@Schema(description, example)DTO 字段字段说明

启用/禁用端点模式

@Operation(summary = "切换启用状态")
@PatchMapping("/{id}/enabled")
public ApiResponse<Void> switchEnabled(
        @PathVariable Long id,
        @RequestParam boolean enabled) {
    facade.switchEnabled(id, enabled);
    return ApiResponse.ok();
}

Facade 层:

@Transactional(rollbackFor = Exception.class)
public void switchEnabled(Long id, boolean enabled) {
    if (enabled) {
        // 启用前检查依赖是否就绪
        validateDependenciesReady(id);
    } else {
        // 禁用前检查是否被其他模块使用
        checkNotInUse(id);
    }
    policyService.switchEnabled(id, enabled);
}

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

84/100Analyzed 2/19/2026

Comprehensive Spring Boot RESTful API development guide covering Controller patterns, 5 endpoint templates (CRUD, pagination, cursor pagination, batch operations), Facade pattern implementation, and OpenAPI annotations. Well-structured with code examples, tables, and clear sections. Good actionability with practical templates. Minor gaps in security coverage. Located in dedicated skills folder with proper metadata.

70
85
80
85
90

Metadata

Licenseunknown
Version-
Updated2/14/2026
Publisherjianyun8023

Tags

api