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 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 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 handleException(Exception e) { log.error("系统异常", e); ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return Result.error(500, "系统繁忙,请稍后重试"); } /** * 处理其他异常 */ @ExceptionHandler(IllegalArgumentException.class) public Result 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 methodArgumentNotValidExceptionHandle(MethodArgumentNotValidException ex, HttpServletRequest request) { log.error("Unhandled RequestParamException from URL [{}]", request.getRequestURI(), ex); List allErrors = ex.getBindingResult().getAllErrors(); List 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 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 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 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 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 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 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 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 handleNullPointerException(NullPointerException e) { log.error("空指针异常", e); ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return Result.error(500, "系统繁忙,请稍后重试"); } }