接上个内容:
一. 需求说明
参与过前后端开发的后端开发人员就明白在项目接口开发中有一套规范的接口返回格式的必要性.这里我主要是结合了我之前项目和网上资源自己定义的一套接口返回规范.作为项目综合练习使用.有需要的同学可以参考下.如果有更好的实现方式欢迎留言
二. 实现方案
在common项目中定义一套统一的接口返回规范,项目的所有接口返回都需要按照这套规范开发.
- ResulCode:返回代码的父类接口,规定了返回结果code必须要有的数据结构,所有新创建的返回code都需要实现ResulCode接口
- CommonCode:项目公共默认返回结果枚举类,实现ResulCode,并在枚举中列举项目的公共返回code
- Response:结果返回实体类的父接口,规定了最终返回接口的数据结构,例如flag,code,message等字段,所有接口最终返回封装bean都要实现Response
- ResponseResult: 一般接口返回实体类,可以用来返回默认结果
- QueryResult定义的一种查询接口查询数据的结构,例如列表查询需要有的list和total
- QueryResponseResult: list查询接口的返回类型
- ResultCodeConstant: 存放常量
说明:作为顶层的接口和父类,一般来说定义好了之后就不会再变更,实现类则是根据具体的业务场景定义的,例如在CommonCode定义了公共的接口返回code,如果有新的返回结果,可以在这个类里面添加,也可以根据需要新建一个例如OrderCode去实现.还有如果有新的查询结构类型,也可以考虑新增QueryResult,QueryResponseResult
三. 代码实现
- 打开项目,这个功能主要是作为公共模块,所以将代码写在common模块中,打开common模块,新建package和类,大概如下
- 常量类 ResultCodeConstant,将一些固定值定义为常量
public class ResultCodeConstant {
public static final String SUCCESS = "success";
public static final String FAIL = "fail";
public static final int SUCCESS_CODE = 10000;
public static final String MSG_SUCCESS = "操作成功";
public static final String MSG_SYSTEM_ERROR = "系统异常,请稍后再试";
}
- 定义一个interface基础接口类 ResultCodeBase,接口中规定了所有该接口实现类必须实现的方法
public interface ResultCodeBase {
/**
* @Description: 接口操作成功标识, success成功,fail失败
* @Param
* @return
* @Author chenhaotao
* @Date 2019/1/5 0005 11:24
*/
String flag();
/**
* @Description: 操作代码
* @Param []
* @return int
* @Author chenhaotao
* @Date 2019/1/5 0005 11:26
*/
int code();
/**
* @Description: 提示信息
* @Param []
* @return java.lang.String
* @Author chenhaotao
* @Date 2019/1/5 0005 11:27
*/
String message();
}
4.创建一个enum枚举类,在这个枚举类中,我们可以将项目中接口返回的所有状态值通过枚举的方式列举下来,同时,枚举类需要实现前面的ResultCodeBase接口
@ToString
public enum ResultCodeEnum implements ResultCodeBase {
SUCCESS("success",10000,"操作成功!"),
UNAUTHENTICATED("fail",10001,"此操作需要登陆系统!"),
UNAUTHORISE("fail",10002,"权限不足,无权操作!"),
INVALID_PARAM("fail",10003,"非法参数!"),
FAIL("fail",11111,"操作失败!"),
SERVER_ERROR("fail",99999,"抱歉,系统繁忙,请稍后重试!");
//操作是否成功
String flag;
//操作代码
int code;
//提示信息
String message;
private ResultCodeEnum(String flag,int code, String message){
this.flag = flag;
this.code = code;
this.message = message;
}
@Override
public String flag() {
return flag;
}
@Override
public int code() {
return code;
}
@Override
public String message() {
return message;
}
}
前面部分我们定义了接口返回的各种状态规范,但是接口请求很多时候是需要查询数据返回的,我们还需要定义接口请求数据的返回规范,后面我们继续定义项目最终返回到前端的responsResult类
5.新建一个接口 ResponsResultBase,规定了一个接口最基本的返回数据结构
public interface ResponsResultBase {
public static final String SUCCESS = ResultCodeConstant.SUCCESS;
public static final int SUCCESS_CODE = ResultCodeConstant.SUCCESS_CODE;
public static final String MSG_SUCCESS = ResultCodeConstant.MSG_SUCCESS;
}
6.新建实现类 ResponsResultImpl,实现ResponsResultBase,自定义构造方法,传入枚举类,以及提供默认成功和失败的返回方法,主要目的是实现将前面定义的枚举类引入进来
@Data
@ToString
@NoArgsConstructor
public class ResponsResultImpl implements ResponsResultBase {
//操作是否成功
String flag = SUCCESS;
//操作代码
int code = SUCCESS_CODE;
//提示信息
String message = MSG_SUCCESS;
/**
* @Description: 使用枚举返回类型构建返回结果
* @Param [resultCode]
* @return
* @Author chenhaotao
* @Date 2019/1/5 0005 11:58
*/
public ResponsResultImpl(ResultCodeEnum resultCodeEnum){
this.flag = resultCodeEnum.flag;
this.code = resultCodeEnum.code;
this.message = resultCodeEnum.message;
}
/**
* @Description: 返回成功状态
* @Param []
* @return com.chen.model.web.ResultRespons
* @Author chenhaotao
* @Date 2019/1/5 0005 12:03
*/
public static ResponsResultImpl returnSuccess(){
return new ResponsResultImpl(ResultCodeEnum.SUCCESS);
}
/**
* @Description: 返回失败状态
* @Param []
* @return com.chen.model.web.ResultRespons
* @Author chenhaotao
* @Date 2019/1/5 0005 12:03
*/
public static ResponsResultImpl returnFail(){
return new ResponsResultImpl(ResultCodeEnum.FAIL);
}
}
7.创建一个列表查询结构封装类 ListResult,定义了返回列表的数据结构,可以根据实际项目情况定义
@Data
@ToString
public class ListResult<T> {
//数据列表
private List<T> list;
//数据总数
private long total;
}
8.新建一个最终的返回结果规范result类
@Data
@ToString
public class SCResponsResult extends ResponsResultImpl {
ListResult listResult;
/**
* @param resultCodeEnum
* @return
* @Description: 使用枚举返回类型构建返回list结果
* @Param [resultCode]
* @Author chenhaotao
* @Date 2019/1/5 0005 11:58
*/
public SCResponsResult(ResultCodeEnum resultCodeEnum, ListResult listResult) {
super(resultCodeEnum);
this.listResult = listResult;
}
}
- 最后,可以在web模块编写测试类
@RestController
public class TestController {
//http://localhost:31001/test
@RequestMapping("test")
public Object test(){
ListResult listResult = new ListResult();
List<String> list = new ArrayList<>();
list.add("11111");
list.add("22222");
listResult.setList(list);
listResult.setTotal(list.size());
SCResponsResult result = new SCResponsResult(ResultCodeEnum.SUCCESS,listResult);
return result;
}
}
最终浏览器显示结果:
完结撒花 ✿✿ヽ(°▽°)ノ✿.
最后再啰嗦一下,虽然刚开始看代码会觉得比较复杂很麻烦,但是一个项目规范接口数据结构是很有必要的,而且这个规范定好之后也不需要怎么修改,后续业务如果有新的拓展也只要在枚举类那边新增新的返回状态,如果接口查询的数据结构有新的变化,只需新定义一个类似ListResult类,并在SCResponResult中新建一个构造方法即可.