如今SpringBoot框架为我们提供了一个极为方便的搭建微服务项目的方案,但是,在使用SpringBoot进行微服务开发时,我们并不能一上来就写代码(当然,如果一上来就写也没什么问题),我们还应该提前指定一些开发规范,否则代码写到后面会越写越烂,毫无规范可言。
我通过平时的开发,总结了一套关于统一接口返回类型以及统一异常处理的规范,仅供参考。
接口返回值类型规范
如今的后台开发,接口规范基本遵循Restful风格,因此后台往前端传递的数据中往往需要包含如下内容:
- 操作是否成功
- 状态码
- 详细信息
- 实体类数据
因此可以规范一个统一的返回实体类ResponseResult,它包含四个成员: boolean success,HttpStatus code,String message,T data,其中code可以自行定义,比如使用整数代替,当然这里使用Spring提供的状态码,不用自己去定义状态码了。
ResponseResult可以如下定义:
public class ResponseResult<T> {
private boolean success;//是否操作成功
private HttpStatus code;//操作状态码,rest风格
private String message;//操作结果详细信息
private T data;//实体类数据
public ResponseResult(ResultCode rc) {
this.success = rc.success();
this.code = rc.code();
this.message = rc.message();
}
public ResponseResult(ResultCode rc, T data) {
this.success = rc.success();
this.code = rc.code();
this.message = rc.message();
this.data = data;
}
//getter&setter方法
}
将接口的返回值都统一使用这个实体类,这样前台接收数据也就能够进行统一。
由于success,code,message三个属性与实体类data关系不大,且可以通用,我们可以单独拎出来,构造一个枚举,以便通用:
public enum ResultCode {
ADD_ITEM_SUCCESS(true, HttpStatus.CREATED,"添加商品成功!"),
NAME_CANNOT_BE_NULL(false, HttpStatus.BAD_REQUEST, "名称不能为空"),
;
//操作是否成功
boolean success;
//操作代码
HttpStatus code;
//提示信息
String message;
private ResultCode(boolean success, HttpStatus code, String message){
this.success = success;
this.code = code;
this.message = message;
}
//getter&setter
}
统一异常处理
开发过程中少不了要处理异常,在SpringBoot微服务中可以这样进行异常的统一处理:
Spring帮我们写了一个通知,其原理是Aop,注解为@ControllerAdvice,它能够默认拦截所有带@Controller注解的类,拦截之后可以写增强功能。在类的方法上加上注解@ExceptionHandler(XxxException.class),就能捕获所有指定的异常:
@ControllerAdvice
public class CommonExceptionHandler {
@ExceptionHandler(MyException.class)
@ResponseBody
public ResponseResult<Void> exceptionHandle(MyException e){
ResultCode rc = e.getExceptionEnum();
return new ResponseResult<>(rc);
}
}
这里需要注意的是:CommonExceptionHandler类和Controller类都要能被SpringBoot扫描到!
自定义异常
在代码中想要手动抛出异常,如果不想被try…catch,那么可以自己定义异常,该异常需要包含“是否成功”,“状态码”,“错误信息”,ResultCode刚好包含这三个属性,因此可以直接将ResultCode作为成员:
public class MyException extends RuntimeException{
private ResultCode resultCode;
public MyException(ResultCode resultCode) {
this.resultCode = resultCode;
}
public MyException() {
}
public ResultCode getExceptionEnum() {
return resultCode;
}
public void setExceptionEnum(ResultCode resultCode) {
this.resultCode = resultCode;
}
}
测试
如下是我快速搭好的一个微服务框架:
controller测试代码:
service测试代码:
使用postman工具测试:
正常情况:
异常情况:
代码GitHub链接:https://github.com/ithushuai/exception-demo