定义返回数据模型
@Getter
public class Result<T> {
private T data;
private String msg;
private int code;
private long timestamp = System.currentTimeMillis();
public Result(T data) {
this.data = data;
this.code = ErrorCodeEnum.OK.getCode();
this.msg = ErrorCodeEnum.OK.getMsg();
}
public Result(ErrorCodeEnum codeEnum) {
this.code = codeEnum.getCode();
this.msg = codeEnum.getMsg();
}
public Result(T data, ErrorCodeEnum codeEnum) {
this.data = data;
this.code = codeEnum.getCode();
this.msg = codeEnum.getMsg();
}
public Result(ErrorCodeEnum codeEnum, String msg) {
this.code = codeEnum.getCode();
this.msg = codeEnum.getMsg();
if (!StringUtils.isEmpty(msg)) {
this.msg = msg;
}
}
}
定义返回数据编码(枚举类)
@Getter
public enum ErrorCodeEnum {
FAIL(-1, "未处理异常"),
OK(1, "ok"),
RPC_FAIL(2, "rpc接口请求失败");
.......
private int code;
private String msg;
ErrorCodeEnum(int code, String msg) {
this.msg = msg;
this.code = code;
}
}
定义异常数据模型
public class AppException extends RuntimeException {
private ErrorCodeEnum codeEnum;
public AppException(ErrorCodeEnum codeEnum) {
super();
this.codeEnum = codeEnum;
}
public AppException(ErrorCodeEnum codeEnum, String message) {
super(message);
this.codeEnum = codeEnum;
}
public ErrorCodeEnum getCodeEnum() {
return codeEnum;
}
}
编写自定义的控制器增强器
@Slf4j
@ControllerAdvice
public class AppResponseBodyHandler implements ResponseBodyAdvice<Object> {
//定义不走控制器增强器的返回类型
private static final List<Class<?>> notSupports = Arrays.asList(String.class, void.class, Result.class, ServletResponse.class, ResponseEntity.class);
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
Class<?> parameterType = methodParameter.getParameterType();
if (notSupports.contains(parameterType)) {
return false;
}
return true;
}
//封装返回数据
@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
if (o != null) {
return new Result<>(o);
}
return null;
}
// 全局异常捕捉处理
@ResponseBody
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(value = Throwable.class)
public Result errorHandler(Throwable e) {
log.error(e.toString(), e);
return new Result(FAIL, e.getMessage());
}
// 全局异常捕捉处理-自定义异常类
@ResponseBody
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(value = AppException.class)
public Result errorHandler(AppException e) {
log.error(e.toString(), e);
return new Result(e.getCodeEnum(), e.getMessage());
}
// 全局异常捕捉处理-参数验证异常
@ResponseBody
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public Result allExceptionHandler(MethodArgumentNotValidException e) {
MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e;
BindingResult bindingResult = ex.getBindingResult();
StringBuilder errMsg = new StringBuilder(bindingResult.getFieldErrors().size() * 16);
for (int i = 0; i < bindingResult.getFieldErrors().size(); i++) {
if (i > 0) {
errMsg.append(",");
}
FieldError error = bindingResult.getFieldErrors().get(i);
errMsg.append(error.getField() + ":" + error.getDefaultMessage());
}
return new Result(2999, errMsg.toString());
}
}
测试
下列测试接口返回的数据类型为List 或 运行时出现异常 或 代码中手动抛出异常
其返回结果最终都是Result风格
@RestController
public class TestController {
@GetMapping(value = "/v1/t1")
public List<TestResp> t1() {
List<TestResp> str = new ArrayList<>();
TestResp testResp = new TestResp();
testResp.setName("Jaye1");
str.add(testResp);
TestResp testResp1 = new TestResp();
testResp1.setName("Jaye2");
str.add(testResp1);
TestResp testResp2 = new TestResp();
testResp2.setName("Jaye3");
str.add(testResp2);
return str;
}
/* 返回结果
{
"data":
[
{"name": "Jaye1"},
{"name": "Jaye2"},
{"name": "Jaye3"}
],
"msg": "ok",
"code": 1,
"timestamp": 1571810712022
}
*/
@GetMapping(value = "/v1/t2")
public void t2() {
int i = 1 / 0;
}
/* 返回结果
{"data":null,"msg":"/ by zero","code":-1,"timestamp":1571810984834}*/
@GetMapping(value = "/v1/t3")
public void t3() {
throw new AppException(RPC_FAIL, "rpc接口rpcDepot.getDepot()返回信息失败");
}
/* 返回结果
{"data":null,"msg":"rpc接口rpcDepot.getDepot()返回信息失败","code":2,"timestamp":1571811083494}*/
@GetMapping(value = "/v1/t4")
public void t4() {
throw new AppException(FAIL);
}
/* 返回结果
{"data":null,"msg":"未处理异常","code":-1,"timestamp":1571811148791}*/
}