package com.youlai.system.common.exception; import cn.hutool.core.util.StrUtil; import com.fasterxml.jackson.core.JsonProcessingException; import com.youlai.system.common.result.Result; import com.youlai.system.common.result.ResultCode; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.TypeMismatchException; import org.springframework.context.support.DefaultMessageSourceResolvable; import org.springframework.http.HttpStatus; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.jdbc.BadSqlGrammarException; import org.springframework.validation.BindException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; import org.springframework.web.servlet.NoHandlerFoundException; import jakarta.servlet.ServletException; import jakarta.validation.ConstraintViolation; import jakarta.validation.ConstraintViolationException; import java.sql.SQLSyntaxErrorException; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; /** * 全局系统异常处理器 *

* 调整异常处理的HTTP状态码,丰富异常处理类型 * * @author Gadfly * @since 2020-02-25 13:54 **/ @RestControllerAdvice @Slf4j public class GlobalExceptionHandler { @ExceptionHandler(BindException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result processException(BindException e) { log.error("BindException:{}", e.getMessage()); String msg = e.getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(";")); return Result.failed(ResultCode.PARAM_ERROR, msg); } /** * RequestParam参数的校验 * * @param e * @param * @return */ @ExceptionHandler(ConstraintViolationException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result processException(ConstraintViolationException e) { log.error("ConstraintViolationException:{}", e.getMessage()); String msg = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(";")); return Result.failed(ResultCode.PARAM_ERROR, msg); } /** * RequestBody参数的校验 * * @param e * @param * @return */ @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result processException(MethodArgumentNotValidException e) { log.error("MethodArgumentNotValidException:{}", e.getMessage()); String msg = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(";")); return Result.failed(ResultCode.PARAM_ERROR, msg); } @ExceptionHandler(NoHandlerFoundException.class) @ResponseStatus(HttpStatus.NOT_FOUND) public Result processException(NoHandlerFoundException e) { log.error(e.getMessage(), e); return Result.failed(ResultCode.RESOURCE_NOT_FOUND); } /** * MissingServletRequestParameterException */ @ExceptionHandler(MissingServletRequestParameterException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result processException(MissingServletRequestParameterException e) { log.error(e.getMessage(), e); return Result.failed(ResultCode.PARAM_IS_NULL); } /** * MethodArgumentTypeMismatchException */ @ExceptionHandler(MethodArgumentTypeMismatchException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result processException(MethodArgumentTypeMismatchException e) { log.error(e.getMessage(), e); return Result.failed(ResultCode.PARAM_ERROR, "类型错误"); } /** * ServletException */ @ExceptionHandler(ServletException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result processException(ServletException e) { log.error(e.getMessage(), e); return Result.failed(e.getMessage()); } @ExceptionHandler(IllegalArgumentException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result handleIllegalArgumentException(IllegalArgumentException e) { log.error("非法参数异常,异常原因:{}", e.getMessage(), e); return Result.failed(e.getMessage()); } @ExceptionHandler(JsonProcessingException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result handleJsonProcessingException(JsonProcessingException e) { log.error("Json转换异常,异常原因:{}", e.getMessage(), e); return Result.failed(e.getMessage()); } /** * HttpMessageNotReadableException */ @ExceptionHandler(HttpMessageNotReadableException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result processException(HttpMessageNotReadableException e) { log.error(e.getMessage(), e); String errorMessage = "请求体不可为空"; Throwable cause = e.getCause(); if (cause != null) { errorMessage = convertMessage(cause); } return Result.failed(errorMessage); } @ExceptionHandler(TypeMismatchException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result processException(TypeMismatchException e) { log.error(e.getMessage(), e); return Result.failed(e.getMessage()); } @ExceptionHandler(BadSqlGrammarException.class) @ResponseStatus(HttpStatus.FORBIDDEN) public Result handleBadSqlGrammarException(BadSqlGrammarException e) { log.error(e.getMessage(), e); String errorMsg = e.getMessage(); if (StrUtil.isNotBlank(errorMsg) && errorMsg.contains("denied to user")) { return Result.failed(ResultCode.FORBIDDEN_OPERATION); } else { return Result.failed(e.getMessage()); } } @ExceptionHandler(SQLSyntaxErrorException.class) @ResponseStatus(HttpStatus.FORBIDDEN) public Result processSQLSyntaxErrorException(SQLSyntaxErrorException e) { log.error(e.getMessage(), e); return Result.failed(e.getMessage()); } @ExceptionHandler(BusinessException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result handleBizException(BusinessException e) { log.error("biz exception: {}", e.getMessage()); if (e.getResultCode() != null) { return Result.failed(e.getResultCode()); } return Result.failed(e.getMessage()); } @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result handleException(Exception e) { log.error("unknown exception: {}", e.getMessage()); return Result.failed(e.getLocalizedMessage()); } /** * 传参类型错误时,用于消息转换 * * @param throwable 异常 * @return 错误信息 */ private String convertMessage(Throwable throwable) { String error = throwable.toString(); String regulation = "\\[\"(.*?)\"]+"; Pattern pattern = Pattern.compile(regulation); Matcher matcher = pattern.matcher(error); String group = ""; if (matcher.find()) { String matchString = matcher.group(); matchString = matchString.replace("[", "").replace("]", ""); matchString = "%s字段类型错误".formatted(matchString.replaceAll("\\\"", "")); group += matchString; } return group; } }