com.emily.infrastructure.web.exception.handler.DefaultGlobalExceptionHandler Maven / Gradle / Ivy
The newest version!
package com.emily.infrastructure.web.exception.handler;
import com.emily.infrastructure.web.exception.entity.BasicException;
import com.emily.infrastructure.web.exception.type.AppStatusType;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.ValidationException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.ErrorResponseException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingRequestValueException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.UnknownContentTypeException;
import org.springframework.web.method.HandlerMethod;
import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException;
/**
* 控制并统一处理异常类 @ExceptionHandler标注的方法优先级问题,它会找到异常的最近继承关系,也就是继承关系最浅的注解方法
*
* @author Emily
* @since 1.0
*/
@RestControllerAdvice
public class DefaultGlobalExceptionHandler extends GlobalExceptionCustomizer {
/**
* 未知异常
*
* @param e 异常
* @param request 请求对象
* @param handlerMethod 方法对象
* @return 异常处理后返回给用户的对象
*/
@ResponseBody
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler(value = {
Exception.class,
RuntimeException.class,
IOException.class,
})
public Object exceptionHandler(Exception e, HttpServletRequest request, HandlerMethod handlerMethod) {
recordErrorMsg(e, request);
String message = e.getMessage();
if (e instanceof IOException) {
message = AppStatusType.EXCEPTION.getMessage();
}
return getApiResponseWrapper(handlerMethod, AppStatusType.EXCEPTION.getStatus(), message);
}
/**
* 业务异常
*
* @param e 异常
* @param request 请求对象
* @param handlerMethod 方法对象
* @return 异常处理后返回给用户的对象
*/
@ResponseBody
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler(BasicException.class)
public Object basicException(BasicException e, HttpServletRequest request, HandlerMethod handlerMethod) {
recordErrorMsg(e, request);
return getApiResponseWrapper(handlerMethod, e.getStatus(), e.getMessage());
}
/**
* 非法代理
*
* @param e 异常
* @param request 请求对象
* @param handlerMethod 方法对象
* @return 异常处理后返回给用户的对象
*/
@ResponseBody
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler(UndeclaredThrowableException.class)
public Object undeclaredThrowableException(UndeclaredThrowableException e, HttpServletRequest request, HandlerMethod handlerMethod) {
recordErrorMsg(e, request);
Throwable throwable = e.getUndeclaredThrowable();
if (throwable != null) {
return getApiResponseWrapper(handlerMethod, AppStatusType.ILLEGAL_PROXY.getStatus(), throwable.getMessage());
}
return getApiResponseWrapper(handlerMethod, AppStatusType.ILLEGAL_PROXY);
}
/**
* API-控制器方法参数Validated参数绑定异常
* 1. BindException[MethodArgumentNotValidException]示例如下:
* {@code
* public class Job implements Serializable {
* //@NotNull(message = "不可为空")
* private Long id;
* private Long jobNumber;
* //@NotEmpty(message = "描述不可以为空")
* private String jobDesc;
* public String a;
* }
* }
* 2. ValidationException[ConstraintViolationException](Get请求参数校验,如@NotEmpty、@NotNull等等)示例如下:
* {@code
* @GetMapping("validParam")
* public String validParam(@Validated @NotEmpty(message = "不可为空") String username){
* return username;
* }
* }
*
* @param e 异常
* @param request 请求对象
* @param handlerMethod 方法对象
* @return 异常处理后返回给用户的对象
*/
@ResponseBody
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler(value = {
IllegalArgumentException.class,
HttpMessageNotReadableException.class,
ErrorResponseException.class,
MissingRequestValueException.class,
TypeMismatchException.class,
BindException.class,
ValidationException.class
})
public Object illegalArgumentException(Exception e, HttpServletRequest request, HandlerMethod handlerMethod) {
recordErrorMsg(e, request);
String message = AppStatusType.ILLEGAL_ARGUMENT.getMessage();
try {
//当用@Valid注释的参数验证失败时引发异常。从5.3起扩展BindException。
if (e instanceof MethodArgumentNotValidException ex) {
// ex.getFieldError() == null时,表示校验参数的注解标注在类上,否则就在实体类字段上
message = ex.getFieldError() == null ? ex.getGlobalError().getDefaultMessage() : ex.getFieldError().getDefaultMessage();
} else if (e instanceof BindException ex) {
message = ex.getFieldError() == null ? ex.getGlobalError().getDefaultMessage() : ex.getFieldError().getDefaultMessage();
} else if (e instanceof ConstraintViolationException ex) {
// ValidationException的子类
message = ex.getConstraintViolations().stream().findFirst().get().getMessageTemplate();
} else if (e instanceof IllegalArgumentException ex) {
message = ex.getMessage();
}
} catch (Exception ignored) {
}
return getApiResponseWrapper(handlerMethod, AppStatusType.ILLEGAL_ARGUMENT.getStatus(), message);
}
/**
* API-请求method不匹配
* 不支持HandlerMethod handlerMethod参数
*
* @param e 异常
* @param request 请求对象
* @return 异常处理后返回给用户的对象
*/
@ResponseBody
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public Object httpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e, HttpServletRequest request) {
recordErrorMsg(e, request);
return getApiResponseWrapper(null, AppStatusType.METHOD_NOT_ALLOWED);
}
/**
* 数字格式异常
*
* @param e 异常
* @param request 请求对象
* @param handlerMethod 方法对象
* @return 异常处理后返回给用户的对象
*/
@ResponseBody
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler(value = {
NumberFormatException.class,
ArithmeticException.class,
IndexOutOfBoundsException.class,
NullPointerException.class,
ClassCastException.class
})
public Object numberFormatException(Exception e, HttpServletRequest request, HandlerMethod handlerMethod) {
recordErrorMsg(e, request);
return getApiResponseWrapper(handlerMethod, AppStatusType.ILLEGAL_DATA);
}
/**
* 非法访问
*
* @param e 异常
* @param request 请求对象
* @param handlerMethod 方法对象
* @return 异常处理后返回给用户的对象
*/
@ResponseBody
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler(value = {
UnknownContentTypeException.class,
ResourceAccessException.class
})
public Object unknownContentTypeException(Exception e, HttpServletRequest request, HandlerMethod handlerMethod) {
recordErrorMsg(e, request);
return getApiResponseWrapper(handlerMethod, AppStatusType.ILLEGAL_ACCESS);
}
}