Appearance
API设计规范
🔌 接口标准:JPwise项目的API设计规范和最佳实践
📋 目录
HTTP方法规范
🚨 重要:只使用GET和POST方法
java
// ✅ 正确:JPwise项目标准
@GetMapping // 查询操作
@PostMapping // 创建、更新、删除操作
// ❌ 错误:不要使用其他HTTP方法
@PutMapping // 不使用
@DeleteMapping // 不使用
@PatchMapping // 不使用
标准接口设计
java
@RestController
@RequestMapping("/api/extend/Business")
public class BusinessController {
// 查询列表 - GET
@BuildQuery
@GetMapping
public ActionResult<PageListVO<BusinessEntity>> getList(QueryBuilder pagination) { }
// 获取详情 - GET
@GetMapping("/{id}")
public ActionResult<BusinessEntity> getInfo(@PathVariable String id) { }
// 创建数据 - POST
@PostMapping
public ActionResult<String> create(@Valid @RequestBody BusinessEntity entity) { }
// 更新数据 - POST (不是PUT)
@PostMapping("/update/{id}")
public ActionResult<String> update(@PathVariable String id, @Valid @RequestBody BusinessEntity entity) { }
// 删除数据 - POST (不是DELETE)
@PostMapping("/{id}")
public ActionResult<String> delete(@PathVariable String id) { }
}
URL路径设计
基础路径规范
java
// 标准格式:/api/{模块}/{资源}
@RequestMapping("/api/extend/LeaveApplication") // 业务扩展模块
@RequestMapping("/api/system/User") // 系统模块
@RequestMapping("/api/workflow/Task") // 工作流模块
@RequestMapping("/api/file/Upload") // 文件模块
模块路径映射
java
jpwise-extend → /api/extend/* // 业务扩展
jpwise-system → /api/system/* // 系统功能
jpwise-workflow → /api/workflow/* // 工作流
jpwise-file → /api/file/* // 文件管理
jpwise-hr → /api/hr/* // 人力资源
资源操作路径
java
// 基础CRUD操作
GET /api/extend/Business // 查询列表(分页)
GET /api/extend/Business/{id} // 查询详情
POST /api/extend/Business // 创建
POST /api/extend/Business/update/{id} // 更新
POST /api/extend/Business/{id} // 删除
// 批量操作
POST /api/extend/Business/Actions/Import // 批量导入
POST /api/extend/Business/Actions/Export // 批量导出
POST /api/extend/Business/Actions/BatchDelete // 批量删除
// 业务操作
POST /api/extend/Business/{id}/submit // 提交
POST /api/extend/Business/{id}/approve // 审批
POST /api/extend/Business/{id}/reject // 拒绝
URL命名规范
- 使用名词,不使用动词
- 资源名称使用驼峰命名
- 路径参数用小写
- 批量操作放在
/Actions/
下
请求参数规范
查询参数 - QueryBuilder
java
// ✅ 使用@BuildQuery注解自动构建查询参数
@BuildQuery
@GetMapping
public ActionResult<PageListVO<Entity>> getList(QueryBuilder pagination) {
// pagination自动包含:
// - currentPage: 当前页码
// - pageSize: 页大小
// - keyword: 搜索关键字
// - condition: 其他查询条件
}
// 前端传参示例
// GET /api/extend/Business?currentPage=1&pageSize=10&keyword=测试&status=APPROVED
请求体参数
java
// 创建和更新直接使用实体类
@PostMapping
public ActionResult<String> create(@Valid @RequestBody BusinessEntity entity) {
// @Valid 自动验证实体类的约束注解
}
// 复杂操作使用DTO
@PostMapping("/batch")
public ActionResult<String> batchOperation(@RequestBody BatchOperationDTO dto) {
// DTO包含操作类型和数据列表
}
参数验证
java
// 实体类验证注解
public class BusinessEntity extends BaseEntity {
@NotBlank(message = "标题不能为空")
@Size(max = 200, message = "标题长度不能超过200字符")
private String TITLE;
@NotNull(message = "金额不能为空")
@DecimalMin(value = "0.01", message = "金额必须大于0")
private BigDecimal AMOUNT;
@Pattern(regexp = "^(DRAFT|PENDING|APPROVED)$", message = "状态值不正确")
private String STATUS;
}
响应格式规范
统一响应结构 - ActionResult
java
// 成功响应结构
{
"code": 200,
"msg": "操作成功",
"data": {
// 具体业务数据
},
"time": 1692000000000
}
// 分页响应结构
{
"code": 200,
"msg": "查询成功",
"data": [
// 数据列表
],
"pagination": {
"currentPage": 1,
"pageSize": 10,
"totalRow": 100,
"totalPage": 10
},
"time": 1692000000000
}
// 错误响应结构
{
"code": 500,
"msg": "操作失败",
"data": null,
"time": 1692000000000
}
响应方法使用
java
// 成功返回数据
return ActionResult.success(entity);
// 成功返回消息
return ActionResult.success(MsgCode.SU001.get());
// 失败返回
return ActionResult.fail("操作失败");
return ActionResult.fail(MsgCode.FA001.get());
// 分页返回
PaginationVO paginationVO = JsonUtil.getJsonToBean(pagination, PaginationVO.class);
return ActionResult.page(dataList, paginationVO);
状态码规范
java
// 使用项目定义的消息码
public class MsgCode {
public static final MsgCode SU001 = new MsgCode(200, "操作成功");
public static final MsgCode FA001 = new MsgCode(500, "操作失败");
public static final MsgCode FA002 = new MsgCode(500, "数据不存在");
public static final MsgCode FA003 = new MsgCode(500, "数据已存在");
}
分页查询规范
分页参数
java
// 标准分页参数
public class QueryBuilder {
private Integer currentPage = 1; // 当前页,从1开始
private Integer pageSize = 10; // 页大小,默认10
private String keyword; // 搜索关键字
private Map<String, Object> condition; // 其他查询条件
}
分页实现
java
@Service
public class BusinessServiceImpl {
@Override
public List<BusinessEntity> getList(QueryBuilder pagination) {
QueryWrapper queryWrapper = new QueryWrapper();
// 基础过滤
queryWrapper.eq(BusinessEntity::getENABLEDMARK, "1")
.isNull(BusinessEntity::getDELETEUSER);
// 关键字搜索
if (StringUtil.isNotEmpty(pagination.getKeyword())) {
queryWrapper.and((Consumer<QueryWrapper>) w -> {
w.like(BusinessEntity::getTITLE, pagination.getKeyword())
.or((Consumer<QueryWrapper>) ww -> ww.like(BusinessEntity::getCODE, pagination.getKeyword()));
});
}
// 其他条件过滤
Map<String, Object> condition = pagination.getCondition();
if (condition != null) {
if (condition.get("status") != null) {
queryWrapper.eq(BusinessEntity::getSTATUS, condition.get("status"));
}
}
// 分页查询
Page<BusinessEntity> page = new Page<>(pagination.getCurrentPage(), pagination.getPageSize());
Page<BusinessEntity> result = this.page(page, queryWrapper);
// 设置分页数据并返回
return pagination.setData(result.getRecords(), result.getTotalRow());
}
}
前端调用示例
javascript
// GET请求示例
/api/extend/Business?currentPage=1&pageSize=10&keyword=测试&status=APPROVED
// 响应数据
{
"code": 200,
"data": [
// 业务数据列表
],
"pagination": {
"currentPage": 1,
"pageSize": 10,
"totalRow": 25,
"totalPage": 3
}
}
错误处理规范
全局异常处理
java
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(BusinessException.class)
public ActionResult handleBusinessException(BusinessException e) {
log.error("业务异常:{}", e.getMessage());
return ActionResult.fail(e.getMessage());
}
@ExceptionHandler(DataException.class)
public ActionResult handleDataException(DataException e) {
log.error("数据异常:{}", e.getMessage());
return ActionResult.fail("数据异常:" + e.getMessage());
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ActionResult handleValidationException(MethodArgumentNotValidException e) {
String message = e.getBindingResult().getFieldErrors().stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.joining(", "));
return ActionResult.fail("参数验证失败:" + message);
}
}
业务异常抛出
java
// Controller层
@PostMapping
public ActionResult<String> create(@Valid @RequestBody BusinessEntity entity) {
try {
businessService.create(entity);
return ActionResult.success(MsgCode.SU001.get());
} catch (BusinessException e) {
return ActionResult.fail(e.getMessage());
}
}
// Service层
@Override
public void create(BusinessEntity entity) {
if (StringUtil.isEmpty(entity.getTITLE())) {
throw new BusinessException("标题不能为空");
}
if (entity.getAMOUNT().compareTo(BigDecimal.ZERO) <= 0) {
throw new BusinessException("金额必须大于0");
}
// 业务逻辑处理...
}
接口文档规范
Swagger注解
java
@RestController
@RequestMapping("/api/extend/Business")
@Api(tags = "业务管理")
public class BusinessController {
@ApiOperation(value = "获取业务列表", notes = "支持分页和关键字搜索")
@ApiImplicitParams({
@ApiImplicitParam(name = "currentPage", value = "当前页", defaultValue = "1"),
@ApiImplicitParam(name = "pageSize", value = "页大小", defaultValue = "10"),
@ApiImplicitParam(name = "keyword", value = "搜索关键字")
})
@BuildQuery
@GetMapping
public ActionResult<PageListVO<BusinessEntity>> getList(QueryBuilder pagination) {
// 实现
}
@ApiOperation(value = "创建业务", notes = "创建新的业务记录")
@PostMapping
public ActionResult<String> create(@ApiParam("业务实体") @Valid @RequestBody BusinessEntity entity) {
// 实现
}
}
实体类文档注解
java
@ApiModel("业务实体")
public class BusinessEntity extends BaseEntity {
@ApiModelProperty(value = "业务标题", required = true, example = "测试业务")
private String TITLE;
@ApiModelProperty(value = "业务金额", required = true, example = "1000.00")
private BigDecimal AMOUNT;
@ApiModelProperty(value = "业务状态", allowableValues = "DRAFT,PENDING,APPROVED", example = "DRAFT")
private String STATUS;
}
接口设计最佳实践
1. RESTful风格适配
虽然只使用GET/POST,但URL设计仍遵循RESTful原则:
- 资源用名词,不用动词
- 层级关系清晰
- 语义明确
2. 统一性原则
- 所有接口返回格式统一
- 参数命名风格统一
- 错误处理方式统一
3. 可扩展性
- 预留扩展字段
- 版本控制考虑
- 向后兼容保证
4. 安全性
- 参数验证完整
- 权限控制到位
- 敏感信息过滤
5. 性能考虑
- 分页查询必须
- 大数据量导出异步处理
- 缓存策略合理
接口测试规范
单元测试
java
@SpringBootTest
@AutoConfigureMockMvc
class BusinessControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
void testGetList() throws Exception {
mockMvc.perform(get("/api/extend/Business")
.param("currentPage", "1")
.param("pageSize", "10"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(200));
}
@Test
void testCreate() throws Exception {
BusinessEntity entity = new BusinessEntity();
entity.setTITLE("测试标题");
entity.setAMOUNT(new BigDecimal("1000"));
mockMvc.perform(post("/api/extend/Business")
.contentType(MediaType.APPLICATION_JSON)
.content(JsonUtil.getObjectToString(entity)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(200));
}
}
💡 提示:良好的API设计是系统稳定性和可维护性的基础。遵循这些规范,可以确保接口的一致性和可预测性,提高开发效率和系统质量。