接口规范
定义接口请求方式、出参入参传递方式、接口命名等方式、便于统一规范,方便前后端协作;
请求方式
统一使用POST方式进行数据提交,区别于REST风格接口,有效解决程序员命名难的问题^_^
数据格式使用JSON交互
接口命名
接口统一以/api/模块名称/接口名称格式,且全部采用小写格式,如较为复杂,可使用-作为连接符
正例:
/api/sys/user/add
/api/sys/user/sync-login
反例:
/api/sys/user/addUser
/user/add
请求头
约定请求头传入token参数,token为当前登录用户的令牌,无需登录的业务接口可以不传递
接口入参
接口入参为JSON格式,通过HTTP的Body来传递,注意区别于传统的表单参数,一般为数据传输类,如下:
{
"name":"北京JeeGen互联科技有限公司",
"email":"836487894@qq.com",
"realName":"郭同学",
"mobile":"18603038204"
}
接口出参
返回数据会有一层消息体的封装,约定响应代码,响应消息,响应数据。
{
"msg": "操作成功",
"code": 0,
"data": {
"userCode":"BkBNppIZaxY9IN2h66OW3Y",
"userName": "Van"
}
}
参数名称 | 参数类型 | 参数描述 |
---|---|---|
msg | 字符串 | 后端响应消息,如执行成功失败或具体的提示信息 |
code | 整型 | 0表示为成功,1表示为失败,其它错误号请自行约定 |
data | 对象 | 响应数据对象,可以是任意类型,列表/对象等 |
数据字典
数据字典用于整个系统的数据枚举、可用于数据的分类、下拉选项等内容,系统提供了便捷的方法来使用它,主要场景有出参翻译和数据导出翻译
常规翻译
某个业务接口只需要单表查询,但是其中一个字段,如:pay_method
是数据字典项,原始值为1、2、3分别对应微信支付
支付宝支付
银联支付
,前端返回的数据要求为中文,那么此时可以做如下配置,在数据响应类增加字典注解,如下:
@Dict(dicCode = "pay_method")
@ApiModelProperty(value = "证书分类")
private String payMethod;
注解名称 | 注解类型 | 注解描述 |
---|---|---|
dicCode | 字符 | sys_dic表的code值,sys_dic_value为值列表 |
sys_dic 数据示例:
code | title |
---|---|
pay_method | 支付方式 |
sys_dic_value 数据示例:
dic_code | value | title |
---|---|---|
pay_method | 1 | 微信支付 |
pay_method | 2 | 支付宝支付 |
pay_method | 3 | 银联支付 |
增加此注解后,系统将自动翻译,在响应参数中增加一个以原属性+_dictText
的字段返回,如:
{
"msg": "操作成功",
"code": 0,
"data": {
"payMethod":"1",
"payMethod_dictText": "微信支付"
...
}
}
联表翻译
另外一种情况,关联数据不是系统数据字典的,也支持翻译,比如,某个表中包含用户IDuserId
字段,但前端需要用户姓名,又不想联表查询,此时可以这样做,在响应类加上以下注解:
@Dict(dicCode = "id", dictTable = "sys_user", dicText = "real_name")
private String userId;
注解名称 | 注解类型 | 注解描述 |
---|---|---|
dicCode | 字符 | 关联查询表的外键,如此处userId对应sys_user的id字段,就填写id |
dicTable | 字符 | 要关联查询的表 |
dicText | 字符 | 查询关联表的哪个字段做数据填充 |
以上注解生成的SQL大概为:
SELECT real_name FROM sys_user WHERE id=#{userId} LIMIT 1
增加此注解后,前端响应数据类似:
{
"msg": "操作成功",
"code": 0,
"data": {
"userId":"10001",
"userId_dictText": "张三"
...
}
}
分页实现
后端分页通过MyBatis Puls插件PaginationInterceptor
来实现,系统中主要有两种情况使用它,1是单表直接查询,2是联表自定义分页查询
单表分页
对于单表,不需要连表查询的简单场景,不需要额外定义SQL,直接使用MyBatisPlus进行分页查询
/**
* 直接使用QueryWrapper来实现单表查询分页
*/
@Override
public IPage<SysNoticeDTO> paging(PagingReqDTO<SysNoticeDTO> reqDTO) {
//查询条件
QueryWrapper<SysNotice> wrapper = new QueryWrapper<>();
// 请求参数
SysNoticeDTO params = reqDTO.getParams();
if(params!=null){
if(!StringUtils.isBlank(params.getTitle())){
wrapper.lambda().like(SysNotice::getTitle, params.getTitle());
}
if(params.getState()!=null){
wrapper.lambda().eq(SysNotice::getState, params.getState());
}
}
wrapper.lambda().orderByDesc(SysNotice::getCreateTime);
//获得数据
IPage<SysNotice> page = this.page(reqDTO.toPage(), wrapper);
//转换结果
IPage<SysNoticeDTO> pageData = JSON.parseObject(JSON.toJSONString(page), new TypeReference<Page<SysNoticeDTO>>(){});
return pageData;
}
自定义分页
对于相对复杂的查询、需要多表连接查询、显然上述方法无法满足需求,此时我们需要写自定义语句来实现分页,如下:
在NoticeMapper.java中定义以下接口,注意第一个参数应为Page分页对象,有了此对象,MyBatisPlus会自动完成分页的操作
/**
* 分页统计总览
* @param page
* @param query
* @param openType
* @return
*/
IPage<SysNoticeDTO> paging(Page page, @Param("query") SysNoticeReqDTO query);
NoticeMapper.xml 定义查询语句,语句同普通的列表查询无异,如:
<select id="paging" resultMap="BaseResultMap">
SELECT * FROM sys_notice
<where>
<if test="query!=null">
<if test="query.title!=null and query.title!=''">
AND title LIKE CONCAT(#{query.title},'%')
</if>
</if>
</where>
</select>