|
|
@@ -0,0 +1,168 @@
|
|
|
+package com.poyee.exception;
|
|
|
+
|
|
|
+import com.poyee.res.Result;
|
|
|
+import com.poyee.utils.I18nUtil;
|
|
|
+import com.poyee.utils.ServletUtils;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.validation.ObjectError;
|
|
|
+import org.springframework.web.bind.MethodArgumentNotValidException;
|
|
|
+import org.springframework.web.bind.annotation.ExceptionHandler;
|
|
|
+import org.springframework.web.bind.annotation.RestControllerAdvice;
|
|
|
+
|
|
|
+import com.auth0.jwt.exceptions.JWTVerificationException;
|
|
|
+import com.auth0.jwt.exceptions.TokenExpiredException;
|
|
|
+import org.springframework.http.converter.HttpMessageNotReadableException;
|
|
|
+import org.springframework.web.HttpMediaTypeNotSupportedException;
|
|
|
+import org.springframework.web.HttpRequestMethodNotSupportedException;
|
|
|
+import org.springframework.web.bind.MissingServletRequestParameterException;
|
|
|
+import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
|
|
|
+
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
+import java.util.List;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 全局异常处理器
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@RestControllerAdvice
|
|
|
+public class GlobalExceptionHandler {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理业务异常
|
|
|
+ */
|
|
|
+ @ExceptionHandler(BusinessException.class)
|
|
|
+ public Result<Void> handleBusinessException(BusinessException e) {
|
|
|
+ log.warn("业务异常:{}", I18nUtil.getMessage(e.getMessage()));
|
|
|
+ ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
|
|
+ return Result.error(e.getCode(), I18nUtil.getMessage(e.getMessage()));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @ExceptionHandler(RuntimeException.class)
|
|
|
+ public Result<Void> handleRuntimeException(RuntimeException e) {
|
|
|
+ log.warn("运行异常:{}", I18nUtil.getMessage(e.getMessage()));
|
|
|
+ ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
|
|
+ return Result.error(I18nUtil.getMessage(e.getMessage()));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理其他异常
|
|
|
+ */
|
|
|
+ @ExceptionHandler(Exception.class)
|
|
|
+ public Result<Void> handleException(Exception e) {
|
|
|
+ log.error("系统异常", e);
|
|
|
+ ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
|
|
+ return Result.error(500, "系统繁忙,请稍后重试");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理其他异常
|
|
|
+ */
|
|
|
+ @ExceptionHandler(IllegalArgumentException.class)
|
|
|
+ public Result<Void> handleIllegalArgumentException(IllegalArgumentException e) {
|
|
|
+ log.error("参数异常", e);
|
|
|
+ ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
|
|
+ return Result.error(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 参数错误
|
|
|
+ */
|
|
|
+ @ExceptionHandler(value = MethodArgumentNotValidException.class)
|
|
|
+ public Result<Void> methodArgumentNotValidExceptionHandle(MethodArgumentNotValidException ex, HttpServletRequest request) {
|
|
|
+ log.error("Unhandled RequestParamException from URL [{}]", request.getRequestURI(), ex);
|
|
|
+ List<ObjectError> allErrors = ex.getBindingResult().getAllErrors();
|
|
|
+ List<String> collect = allErrors.stream()
|
|
|
+ .map(error -> {
|
|
|
+ String defaultMessage = error.getDefaultMessage();
|
|
|
+ String i18nMessage = I18nUtil.getMessage(defaultMessage);
|
|
|
+ return i18nMessage != null ? i18nMessage : defaultMessage;
|
|
|
+ })
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
|
|
+ return Result.error(HttpServletResponse.SC_BAD_REQUEST, collect.toString());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 缺少请求参数
|
|
|
+ */
|
|
|
+ @ExceptionHandler(MissingServletRequestParameterException.class)
|
|
|
+ public Result<Void> handleMissingServletRequestParameter(MissingServletRequestParameterException e) {
|
|
|
+ log.warn("缺少请求参数:{}", e.getParameterName());
|
|
|
+ ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
|
|
+ return Result.error(HttpServletResponse.SC_BAD_REQUEST, "缺少请求参数:" + e.getParameterName());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 参数类型不匹配
|
|
|
+ */
|
|
|
+ @ExceptionHandler(MethodArgumentTypeMismatchException.class)
|
|
|
+ public Result<Void> handleMethodArgumentTypeMismatch(MethodArgumentTypeMismatchException e) {
|
|
|
+ log.warn("参数类型不匹配:{}", e.getName());
|
|
|
+ ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
|
|
+ return Result.error(HttpServletResponse.SC_BAD_REQUEST, "参数类型不匹配:" + e.getName());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 请求体不可读(JSON格式错误等)
|
|
|
+ */
|
|
|
+ @ExceptionHandler(HttpMessageNotReadableException.class)
|
|
|
+ public Result<Void> handleHttpMessageNotReadable(HttpMessageNotReadableException e) {
|
|
|
+ log.warn("请求体解析失败:{}", e.getMessage());
|
|
|
+ ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
|
|
+ return Result.error(HttpServletResponse.SC_BAD_REQUEST, "请求体格式错误");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 请求方法不支持
|
|
|
+ */
|
|
|
+ @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
|
|
|
+ public Result<Void> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e) {
|
|
|
+ log.warn("请求方法不支持:{}", e.getMethod());
|
|
|
+ ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
|
|
|
+ return Result.error(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "不支持的请求方法:" + e.getMethod());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 媒体类型不支持
|
|
|
+ */
|
|
|
+ @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
|
|
|
+ public Result<Void> handleHttpMediaTypeNotSupported(HttpMediaTypeNotSupportedException e) {
|
|
|
+ log.warn("媒体类型不支持:{}", e.getContentType());
|
|
|
+ ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
|
|
|
+ return Result.error(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, "不支持的媒体类型:" + e.getContentType());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * JWT Token 过期
|
|
|
+ */
|
|
|
+ @ExceptionHandler(TokenExpiredException.class)
|
|
|
+ public Result<Void> handleTokenExpired(TokenExpiredException e) {
|
|
|
+ log.warn("Token已过期:{}", e.getMessage());
|
|
|
+ ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
|
|
+ return Result.error(HttpServletResponse.SC_UNAUTHORIZED, "Token已过期,请重新登录");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * JWT Token 验证失败
|
|
|
+ */
|
|
|
+ @ExceptionHandler(JWTVerificationException.class)
|
|
|
+ public Result<Void> handleJWTVerification(JWTVerificationException e) {
|
|
|
+ log.warn("Token验证失败:{}", e.getMessage());
|
|
|
+ ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
|
|
+ return Result.error(HttpServletResponse.SC_UNAUTHORIZED, "Token无效,请重新登录");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 空指针异常
|
|
|
+ */
|
|
|
+ @ExceptionHandler(NullPointerException.class)
|
|
|
+ public Result<Void> handleNullPointerException(NullPointerException e) {
|
|
|
+ log.error("空指针异常", e);
|
|
|
+ ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
|
|
+ return Result.error(500, "系统繁忙,请稍后重试");
|
|
|
+ }
|
|
|
+}
|