利用注解@RestControllerAdvice 轻轻松松实现全局异常处理
一、定义统一响应体
package com.zhh.demo.common.response;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* @Description: 接口出参统一响应实体
* @Author: zhaoheng
* @CreateTime: 2022-08-05 16:27
*/
@Data
@ApiModel("接口出参统一响应实体")
public class Response<T> implements Serializable {
private static final long serialVersionUID = 3692286106860121474L;
@ApiModelProperty(value = "状态码")
private String code;
@ApiModelProperty(value = "说明")
private String message;
private T data;
public Response(){}
public Response(String code, String message) {
this.code = code;
this.message = message;
}
public Response(String code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
}
package com.zhh.demo.common.response;
import lombok.Getter;
/**
* @Description: 统一响应code和说明
* @Author: zhaoheng
* @CreateTime: 2022-08-05 16:42
*/
public enum ResponseCode {
/** 通用码 **/
FAIL("-1", "系统错误"),
OK("200", "成功"),
/**
* 参考阿里巴巴开发手册
* 错误码为字符串类型,共5位,分两部分组成:错误标识+4位数字编号。
* 例:A0001,A1001,B0001,C0001... A、B、分别代表不通业务或者来源
**/
/** 参数校验不通过 **/
PARAMETER_CHECK_FAILS("A0001","参数校验不通过"),
/** 用户相关 A1xxx **/
USER_NAME_NONSTANDARD("A1002", "用户名不合规");
ResponseCode(String code, String msg) {
this.code = code;
this.msg = msg;
}
@Getter
private String code;
@Getter
private String msg;
}
package com.zhh.demo.common.response;
import com.zhh.demo.entity.common.ResponsePage;
import java.util.List;
/**
* @Description: 接口统一响应实体构造类
* @Author: zhaoheng
* @CreateTime: 2022-08-05 16:37
*/
public class ResponseFactory {
/**
* 默认成功
* @param t
* @param <T>
* @return
*/
public static <T> Response<T> success(T t){
return new Response<T>(ResponseCode.OK.getCode(),ResponseCode.OK.getMsg(),t);
}
/**
* 成功
* @param responseCode 响应code和说明
* @param t
* @param <T>
* @return
*/
public static <T> Response<T> success(ResponseCode responseCode, T t){
return new Response<T>(responseCode.getCode(),responseCode.getMsg(),t);
}
/**
* 成功
* @param responseCode 响应code和说明
* @return
*/
public static <T> Response<T> success(ResponseCode responseCode){
return new Response<T>(responseCode.getCode(),responseCode.getMsg());
}
/**
* 默认失败
* @param <T>
* @return
*/
public static <T> Response<T> error(){
return new Response<T>(ResponseCode.FAIL.getCode(),ResponseCode.FAIL.getMsg());
}
/**
* 失败
* @param responseCode 响应code和说明
* @param t
* @param <T>
* @return
*/
public static <T> Response<T> error(ResponseCode responseCode, T t){
return new Response<T>(responseCode.getCode(),responseCode.getMsg(),t);
}
/**
* 失败
* @param responseCode 响应code和说明
* @return
*/
public static <T> Response<T> error(ResponseCode responseCode){
return new Response<T>(responseCode.getCode(),responseCode.getMsg());
}
/**
* 失败
* @param code 错误码
* @param msg 说明
* @param t 响应数据
* @param <T>
* @return
*/
public static <T> Response<T> error(String code, String msg, T t){
return new Response<T>(code,msg,t);
}
/**
* 失败
* @param code 错误码
* @param msg 说明
* @return
*/
public static <T> Response<T> error(String code, String msg){
return new Response<T>(code,msg);
}
public static <T> ResponsePage pageResult(List<T> list, int total){
return new ResponsePage<T>(list,total);
}
}
二、定义全局异常处理类
package com.zhh.demo.common.exception;
import com.zhh.demo.common.response.Response;
import com.zhh.demo.common.response.ResponseCode;
import com.zhh.demo.common.response.ResponseFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.List;
/**
* @Description: 全局异常处理
* @Author: zhaoheng
* @CreateTime: 2022-08-05 17:33
*/
@Slf4j
@RestControllerAdvice
public class ExceptionHandle {
/**
* 处理Exception异常
* @param exception 异常类型
* @return
*/
@ExceptionHandler(value = Exception.class)
public Response<?> ExceptionHandle(Exception exception){
log.error("系统出现异常:",exception);
return ResponseFactory.error(ResponseCode.FAIL);
}
/**
* 处理业务异常
* @param exception 异常类型
* @return
*/
@ExceptionHandler(value = BaseException.class)
public Response<?> BaseExceptionHandle(BaseExceptionexception){
log.error("系统业务异常:",exception);
return ResponseFactory.error(exception.getCode(),exception.getMsg());
}
/**
* 入参校验异常,校验不通过,抛出异常信息
* @param exception Valid 入参校验异常
* @return
*/
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public Response<?> methodArgumentNotValidExceptionHandle(MethodArgumentNotValidException exception){
log.error("入参校验不通过",exception);
BindingResult bindingResult = exception.getBindingResult();
List<FieldError> fieldErrorList = bindingResult.getFieldErrors();
fieldErrorList.forEach(fieldError -> {
log.info("字段:{},message:{}",fieldError.getField(),fieldError.getDefaultMessage());
});
// 一个一个给调用方返回提示
String message = fieldErrorList.get(0).getDefaultMessage();
return ResponseFactory.error(ResponseCode.PARAMETER_CHECK_FAILS.getCode(), message);
}
}
自定义异常
package com.zhh.demo.common.exception;
import com.zhh.demo.common.response.Response;
import com.zhh.demo.common.response.ResponseCode;
import lombok.Data;
/**
* @Description: 异常基类
* @Author: zhaoheng
* @CreateTime: 2022-08-05 17:22
*/
@Data
public abstract class BaseException extends RuntimeException{
/**
* code码
*/
private String code;
/**
* 异常说明
*/
private String msg;
/**
* 响应体
*/
private Response response;
public BaseException(String code, String msg) {
super(msg);
this.code = code;
this.msg = msg;
this.response = new Response(code,msg);
}
public BaseException(ResponseCode responseCode) {
super(responseCode.getMsg());
this.code = responseCode.getCode();
this.msg = responseCode.getMsg();
this.response = new Response(responseCode.getCode(),responseCode.getMsg());
}
}
三、编写接口测试效果
package com.zhh.demo.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
@Api(tags = "test-api")
@RequestMapping("/api/test")
@RestController
@Validated // 开启入参校验
public class TestController {
@ApiOperation("异常测试")
@PostMapping("/t1")
public String test(){
// 模拟异常
new ArrayList<>().get(1);
return "";
}
}
经过测试,接口抛出异常后会被异常处理类处理,并且给调用端返回指定格式的提示信息
{
"code": "-1",
"message": "系统错误",
"data": null
}