控制层关系到与前端的交互,以项目为单位,提供一致的接口设计、响应数据格式有助于前端快速理解接口对接方式
- 请求方式:
- POST:新增
- GET:查询
- PUT:编辑
- DELETE:删除
- URL:
- 项目名/模块名/功能名
- 例子
*不建议根据参数格式决定请求方式;建议根据业务类型,确定请求方式,进而确定传参形式
针对各模块、功能通用的接口,例如:实体新增、单个实体查询、实体列表查询、实体分页查询、实体编辑、实体删除等。各模块、功能使用统一的规范。
接口名称 | 请求方式 | 传参方式 | 模板 | 示例 |
---|---|---|---|---|
实体新增 | POST | RequestBody | xxx/xxx/实体名 | POST: /onp/resource/ots |
单个实体查询 | GET | PathVariable | xxx/xxx/实体名/{id} | GET: /onp/resource/ots/123456 |
实体列表查询*1 | POST*2 | RequestBody | xxx/xxx/实体名/list | POST: /onp/resource/ots/list |
实体编辑 | PUT | RequestBody | xxx/xxx/实体名 | PUT: /onp/resource/ots |
实体删除 | DELETE | PathVariable | xxx/xxx/实体名 | DELETE: /onp/resource/ots/123456 |
GET请求,不加requestParam导致feign无法接受参数
*1: 实体列表查询包含了分页查询,后端以查询参数中是否携带
pageSize
、pageNum
作为分页的条件。包含上述任一参数的情况,都进行分页处理。pageSize
(单页条数)的默认值为:10,pageNum
(当前页码)的默认值为:0。*2: 此处查询接口之所以使用POST方式,是考虑到参数比较多的情况下使用
body
传参方便以及feign
兼容的因素,为特例。
- 路径传参:常用于传输主键,用于GET
- URL传参:常用于传输查询条件,用于GET、DELETE
- body JSON传参:常用于提交数据至后台,用于POST、PUT
不建议使用Map<String, Object>作为响应或形参
类型名称 | Java类型 | JS类型 | 方式 | 示例 |
---|---|---|---|---|
长整型 | Long | String | 全局配置 Jackson 序列化 | |
日期 | java.util.Date | String | 后端配置统一的序列化、反序列化 格式统一为:"yyyy-MM-dd HH:mm:ss" |
原则上采用下述格式:
{
"success": true,
"code": 10000,
"message": "操作成功",
"data": {}
}
外部参数需要在控制层进行校验,经过校验的参数方可在业务中使用。
外部参数校验包含一下几个方面:
- 存在性校验
- 参数是否存在
- 数据格式校验
- 数字:范围校验
- 字符串:长度校验、正则校验
- 多个参数:组合校验
建议使用 hibernate-validator
框架作为控制层校验框架,目前在onp-resource模块中有部分应用:
@ApiOperation(value = "xxx")
@PostMapping("card/oa")
public void bindOaCardModelToElement(@Validated{group="Add.class"} @RequestBody BindCardModelParam param) {
elementModelService.bindOaCardModel(param.getElementModelId(), param.getCardModels());
}
@Data
public static class BindCardModelParam {
@NotNull
@ApiModelProperty(value = "xxx", required = true)
private Long elementModelId;
@NotNull(group=add.class,Update.class)
@ApiModelProperty(value = "yyy", required = true)
private List<Long> cardModels;
}
{
"success": false,
"code": 10004,
"message": "参数校验失败",
"data": [
{
"field": "cardModels",
"message": "不能为null"
},
{
"field": "elementModelId",
"message": "不能为null"
}
]
}
注意点:
- service 层返回的实体不能是dao层的对象
Vo get(Integer id);
Vo getByBillNo(Integer houseId, String billNo);
批量查询用query
作为前缀,例如根据单据id集合查询
List<Vo> queryByIds(List<Integer> ids);
分页查询用queryPage
PageInfo<XXXVo> queryPage(PageParam<QueryPageVo> pageParam);
- 单个插入用
save
, 返回值为生成的id主键 - 批量插入用
batchSave
,返回值为空
Integer save(Dto dto, OperatorContext optContext)
void batchSave(List<Dto> dtos, OperatorContext optContext)
- 单个修改用
update
, 返回值为空 - 批量插入用
batchUpdate
,返回值为空
void update(Dto dto, OperatorContext optContext)
void batchUpdate(List<Dto> dtos, OperatorContext optContext)
- 单个修改用
remove
, 返回值为空 - 批量插入用
batchRemove
,返回值为空
void remove(Integer id, Long version, OperatorContext optContext)
void batchRemove(List<Dto> dtos, OperatorContext optContext)
- 查询的接口,不允许出现业务异常,如果查询不到,返回空。
- 增删改接口,需要带上OperatorContext,后续需要记录操作日志的情况,直接从这个里面取即可。
- RPC层接口需要参数校验,所以入参实体需要用java validation 相关注解来进行字段约束
- dubbo接口的提供者 和 消费者,均需要开启校验,消费者开启校验的好处是:当参数校验失败后,不再发起rpc请求,减少网络调用
@DubboService(validation="true")
@DubboReference(validation="true")
- RPC接口提供者,例如
RpcXXXServiceImpl
内部,禁止写业务逻辑,统一调相关service接口,具体逻辑在业务实现层处理