1、GlobalExceptionHandler 全局异常处理拦截器,捕获400,405和自定义等controller之后的异常
import com.dm.exception.BSException; import com.dm.model.Result; import com.dm.model.StatusCode; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.ServletRequestBindingException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; import javax.validation.ConstraintViolationException; import java.net.BindException; /** * 解决Controller之后的异常 */ @Slf4j @RestControllerAdvice public class GlobalExceptionHandler { /** * 400 - Bad Request */ @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler({HttpMessageNotReadableException.class, MissingServletRequestParameterException.class, BindException.class, ServletRequestBindingException.class, MethodArgumentNotValidException.class, ConstraintViolationException.class}) public Result handleHttpMessageNotReadableException(Exception e) { log.error("------err------Bad Request: " + e.getMessage(), e); return new Result(StatusCode.BAD_REQUEST, "参数解析失败"); } /** * 405 - Method Not Allowed */ @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED) @ExceptionHandler(HttpRequestMethodNotSupportedException.class) public Result handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) { log.error("------err------Method Not Allowed: " + e.getMessage(), e); return new Result(StatusCode.METHOD_NOT_ALLOWED, "不支持当前请求方法"); } /** * 自定义异常在此捕获 */ @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ExceptionHandler(Throwable.class) public Result handleException(Throwable e) { log.error("------err------Service Run Exception: " + e.getMessage(), e); if (e instanceof BSException) { return new Result(((BSException) e).getCode(), ((BSException) e).getMsg()); } return new Result(StatusCode.SYSTEM_ERR, "服务器运行异常"); } }
注意:自定义异常在方法handleException中进行捕获
2、FrontErrHandler,404异常是全局异常捕获不到的,所以放在FrontErrHandler进行处理
import com.dm.model.Result; import com.dm.model.StatusCode; import io.swagger.annotations.Api; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.web.servlet.error.ErrorController; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 解决Controller之前的异常 */ @RestController @Slf4j @Api(tags = "FrontErrHandler", description = "FrontErrHandler相关接口") public class FrontErrHandler implements ErrorController { @Override public String getErrorPath() { return "/error"; } @GetMapping(value = "/error") @ResponseStatus(HttpStatus.NOT_FOUND) public Object error(HttpServletRequest request, HttpServletResponse response) { log.error("------err------Response Error,HttpCode: " + response.getStatus()); // 错误处理逻辑 int status = response.getStatus(); if (status == 404) { return new Result(StatusCode.REQUEST_NOT_FOUND, "访问地址不存在"); } else if (status == 500) { return new Result(StatusCode.SYSTEM_ERR, "服务器运行异常"); } else if (status >= 100 && status < 200) { return new Result(StatusCode.HTTP_ERROR_100, null); } else if (status >= 300 && status < 400) { return new Result(StatusCode.HTTP_ERROR_300, null); } else if (status >= 400 && status < 500) { return new Result(StatusCode.HTTP_ERROR_400, null); } else { return new Result(StatusCode.SYSTEM_ERR, "服务器运行异常"); } } }
3、捕获到异常以后将返回结果统一封装到Result中,封装Result时有两种方式,
1)采用普通返回码,如返回正常,400,500等可以直接从普通返回码类中拿CODE进行返回的直接封装
return new Result(StatusCode.OK, "添加成功")
return new Result(StatusCode.SYSTEM_ERR, "服务器运行异常");
2)从自定义异常中拿到code和msg封装最终返回,code和msg来自异常枚举
return new Result(((BSException) e).getCode(), ((BSException) e).getMsg());
3)Result定义
import io.swagger.annotations.ApiModel; /** * 返回结果实体类 */ @ApiModel(description = "Result",value = "Result") public class Result<T> { private Integer code;//返回码 private String message;//返回消息 private T data;//返回数据 public Result(Integer code, String message, Object data) { this.code = code; this.message = message; this.data = (T)data; } public Result(Integer code, String message) { this.code = code; this.message = message; } public Result() { this.code = StatusCode.OK; this.message = "执行成功"; } 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; } }
4)普通返回码定义
/** * 普通返回码 */ public class StatusCode { public static final int OK = 200;//成功 public static final int SYSTEM_ERR = 500;//服务器运行异常 public static final int REQUEST_NOT_FOUND = 404;//访问地址不存在 public static final int HTTP_ERROR_100 = 100;//1XX错误 public static final int HTTP_ERROR_300 = 300;//3XX错误 public static final int HTTP_ERROR_400 = 400;//4XX错误 public static final int HTTP_ERROR_500 = 500;//5XX错误 public static final int BAD_REQUEST = 407;//参数解析失败 public static final int METHOD_NOT_ALLOWED = 405;//不支持当前请求方法 }
4、exception目录下定义异常类和异常枚举
1)自定义异常类
public class BSException extends RuntimeException { private int code; private String msg; public BSException(ErrorEnum errEnum, Exception e) { super(e); this.code = errEnum.getCode(); this.msg = errEnum.getMsg(); } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
2)自定义异常枚举
/** * 自定义异Enum */ public enum ErrorEnum { //CUSTOM_EXCEPTION(6007, "自定义异常7"), CUSTOM_EXCEPTION(6008, "自定义异常8"); private final Integer code; private final String msg; public Integer getCode() { return code; } public String getMsg() { return msg; } ErrorEnum(int code, String msg) { this.code = code; this.msg = msg; } }
5、自定义异常的使用
/** * 根据ID查询BsCategory */ @Override public BsCategory findById(Integer id) { try { int i = 1 / 0; } catch (Exception e) { log.info("...err:::{}", e.getMessage()); throw new BSException(ErrorEnum.CUSTOM_EXCEPTION,e); } return bsCategoryMapper.selectById(id); }
6、总结
通过两个全局异常处理器将controller之前和之后的异常全部捕获到,然后通过Result通过封装结果进行返回,利用自定义异常和枚举来定义自己想要处理的异常。