###restful接口统一返回值
使用JsonResult返回请求接口,使用泛型填充返回数据结构。code代表返回值,既可以设置为Integer,也可以设置为String,取决于项目需要。
通常,系统复杂可以使用String类型,标识出错的模块名称以及错误类型。系统简单直接使用Integer标识错误码即可。此处,封装两个函数,success和error。
//JsonResult作为返回值
public class JsonResult<T> {
private Integer code;
private String message;
private T data;
public JsonResult(T data) {
this.code = RtnCodeMsg.SUCCESS.getCode();
this.message = RtnCodeMsg.SUCCESS.getMessage();
this.data = data;
}
public JsonResult(RtnCodeMsg rtnCodeMsg) {
this.code = rtnCodeMsg.getCode();
this.message = rtnCodeMsg.getMessage();
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public static <T> JsonResult<T> success(T data) {
return new JsonResult<T>(data);
}
public static <T> JsonResult<T> error(RtnCodeMsg msg) {
return new JsonResult<T>(msg);
}
}
//返回值封装,定义常用错误码
public class RtnCodeMsg {
private Integer code;
private String message;
public RtnCodeMsg(Integer code, String message) {
this.code = code;
this.message = message;
}
public RtnCodeMsg(BusinessRuntimeException businessRuntimeException) {
this.code = businessRuntimeException.getCode();
this.message = businessRuntimeException.getMessage();
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public RtnCodeMsg fillArgs(Object...args) {
Integer code = this.code;
String message = String.format(this.message, args);
return new RtnCodeMsg(code, message);
}
//通用错误码
public static RtnCodeMsg SUCCESS = new RtnCodeMsg(200, "请求成功");
public static RtnCodeMsg BAD_REQUEST = new RtnCodeMsg(400, "%s");
public static RtnCodeMsg NO_PERMITS = new RtnCodeMsg(401, "%s");
public static RtnCodeMsg INTERNAL_ERROR = new RtnCodeMsg(500, "%s");
//OSS错误码40XXX
public static RtnCodeMsg NOT_EXIST = new RtnCodeMsg(404, "%s");
}
//业务代码中,使用封装后的异常
public class BusinessRuntimeException extends RuntimeException {
private Integer code;
public BusinessRuntimeException() {
super();
}
public BusinessRuntimeException(RtnCodeMsg rtnCodeMsg) {
super(rtnCodeMsg.getMessage());
code = rtnCodeMsg.getCode();
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
@Override
public String getMessage() {
return super.getMessage();
}
}
###restful接口数据封装
请求完成,无论成功与否,可以采用以下方式封装结果。请求返回controlller时,引入ResponseBodyAdvice,进行相应的处理。
同样此处增加全局异常的捕获,对异常结果也进行封装。其中ResponseBodyAdvice用于结果处理。beforeBodyWrite 函数中,如果o是JsonResult,直接返回即可,
否则,则表示处理成功,对结果进行封装即可
@ControllerAdvice(basePackages = "com.hero.test.controller")
@ResponseBody
public class JsonResultResponseBodyAdvice implements ResponseBodyAdvice {
@Override
public boolean supports(MethodParameter methodParameter, Class aClass) {
return true;
}
@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
if (o instanceof JsonResult) {
return o;
}
JsonResult jsonResult = JsonResult.success(o);
if (o instanceof String) {
return JSON.toJSONString(jsonResult);
} else {
return jsonResult;
}
}
@ExceptionHandler(value = Exception.class)
public JsonResult exceptionHandler(HttpServletRequest request, Exception ex) {
if (ex instanceof BindException) {
BindException bindException = (BindException) ex;
List<ObjectError> errors = bindException.getAllErrors();
ObjectError error = errors.get(0);
String errorMsg = error.getDefaultMessage();
return JsonResult.error(RtnCodeMsg.BAD_REQUEST.fillArgs(errorMsg));
}
if (ex instanceof MethodArgumentNotValidException) {
MethodArgumentNotValidException methodArgumentNotValidException = (MethodArgumentNotValidException) ex;
String errorMsg = methodArgumentNotValidException.getBindingResult().getAllErrors().get(0).getDefaultMessage();
return JsonResult.error(RtnCodeMsg.BAD_REQUEST.fillArgs(errorMsg));
}
if (ex instanceof BusinessRuntimeException) {
BusinessRuntimeException businessRuntimeException = (BusinessRuntimeException) ex;
return JsonResult.error(new RtnCodeMsg(businessRuntimeException));
}
return JsonResult.error(INTERNAL_ERROR.fillArgs(ex.getMessage()));
}
}
注意点:
(1)对于返回String类型结果的,要特殊处理,否则系统会报错,提示Cast失败,在源码分析时再做讨论.
(2)对于ControllerAdvice,可以指定对哪些包进行结果的封装,通常指定自身代码所在包。如果不指定,
例如使用Swagger,会导致Swagger查询失败,因为我们对其返回的结果也进行了封装,不符合原有预期。