springboot 全局异常处理器
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通过封装结果进行返回,利用自定义异常和枚举来定义自己想要处理的异常。

浙公网安备 33010602011771号