接口规范

定义接口请求方式、出参入参传递方式、接口命名等方式、便于统一规范,方便前后端协作;

请求方式

统一使用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 数据示例:

codetitle
pay_method支付方式

sys_dic_value 数据示例:

dic_codevaluetitle
pay_method1微信支付
pay_method2支付宝支付
pay_method3银联支付

增加此注解后,系统将自动翻译,在响应参数中增加一个以原属性+_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>

导入导出