212 lines
7.8 KiB
Java
212 lines
7.8 KiB
Java
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;
|
||
|
||
/**
|
||
* 全局系统异常处理器
|
||
* <p>
|
||
* 调整异常处理的HTTP状态码,丰富异常处理类型
|
||
*
|
||
* @author Gadfly
|
||
* @since 2020-02-25 13:54
|
||
**/
|
||
@RestControllerAdvice
|
||
@Slf4j
|
||
public class GlobalExceptionHandler {
|
||
|
||
@ExceptionHandler(BindException.class)
|
||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||
public <T> Result<T> 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 <T>
|
||
* @return
|
||
*/
|
||
@ExceptionHandler(ConstraintViolationException.class)
|
||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||
public <T> Result<T> 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 <T>
|
||
* @return
|
||
*/
|
||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||
public <T> Result<T> 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 <T> Result<T> processException(NoHandlerFoundException e) {
|
||
log.error(e.getMessage(), e);
|
||
return Result.failed(ResultCode.RESOURCE_NOT_FOUND);
|
||
}
|
||
|
||
/**
|
||
* MissingServletRequestParameterException
|
||
*/
|
||
@ExceptionHandler(MissingServletRequestParameterException.class)
|
||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||
public <T> Result<T> processException(MissingServletRequestParameterException e) {
|
||
log.error(e.getMessage(), e);
|
||
return Result.failed(ResultCode.PARAM_IS_NULL);
|
||
}
|
||
|
||
/**
|
||
* MethodArgumentTypeMismatchException
|
||
*/
|
||
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
|
||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||
public <T> Result<T> processException(MethodArgumentTypeMismatchException e) {
|
||
log.error(e.getMessage(), e);
|
||
return Result.failed(ResultCode.PARAM_ERROR, "类型错误");
|
||
}
|
||
|
||
/**
|
||
* ServletException
|
||
*/
|
||
@ExceptionHandler(ServletException.class)
|
||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||
public <T> Result<T> processException(ServletException e) {
|
||
log.error(e.getMessage(), e);
|
||
return Result.failed(e.getMessage());
|
||
}
|
||
|
||
@ExceptionHandler(IllegalArgumentException.class)
|
||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||
public <T> Result<T> handleIllegalArgumentException(IllegalArgumentException e) {
|
||
log.error("非法参数异常,异常原因:{}", e.getMessage(), e);
|
||
return Result.failed(e.getMessage());
|
||
}
|
||
|
||
@ExceptionHandler(JsonProcessingException.class)
|
||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||
public <T> Result<T> handleJsonProcessingException(JsonProcessingException e) {
|
||
log.error("Json转换异常,异常原因:{}", e.getMessage(), e);
|
||
return Result.failed(e.getMessage());
|
||
}
|
||
|
||
/**
|
||
* HttpMessageNotReadableException
|
||
*/
|
||
@ExceptionHandler(HttpMessageNotReadableException.class)
|
||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||
public <T> Result<T> 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 <T> Result<T> processException(TypeMismatchException e) {
|
||
log.error(e.getMessage(), e);
|
||
return Result.failed(e.getMessage());
|
||
}
|
||
|
||
@ExceptionHandler(BadSqlGrammarException.class)
|
||
@ResponseStatus(HttpStatus.FORBIDDEN)
|
||
public <T> Result<T> 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 <T> Result<T> processSQLSyntaxErrorException(SQLSyntaxErrorException e) {
|
||
log.error(e.getMessage(), e);
|
||
return Result.failed(e.getMessage());
|
||
}
|
||
|
||
|
||
@ExceptionHandler(BusinessException.class)
|
||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||
public <T> Result<T> 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 <T> Result<T> 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;
|
||
}
|
||
}
|