cn.k7g.alloy.ioc.processor.EnhanceExceptionResponse Maven / Gradle / Ivy
package cn.k7g.alloy.ioc.processor;
import cn.k7g.alloy.autoconfiguration.EnableOptions;
import cn.k7g.alloy.expose.WebExceptionResponseHandler;
import cn.k7g.alloy.mold.impl.SpelMoldService;
import cn.k7g.alloy.utils.AlloyUtils;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.web.servlet.MultipartProperties;
import org.springframework.context.expression.MapAccessor;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.ReflectivePropertyAccessor;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MissingRequestValueException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.NoHandlerFoundException;
import javax.security.auth.login.AccountExpiredException;
import javax.validation.ConstraintViolationException;
import java.nio.file.AccessDeniedException;
import java.util.Properties;
import java.util.stream.Collectors;
/**
* 增强异常处理器
* @author victor-wu
* @date 2021/9/27 下午1:10
*/
@Slf4j
@RestControllerAdvice
@ConditionalOnBean(EnableOptions.EnhanceExceptionMessage.class)
public class EnhanceExceptionResponse {
public static final String EXCEPTION_MESSAGES_PROPERTIES_BEAN_NAME = "cn.k7g.alloy.ioc.processor.EnhanceExceptionResponse.EXCEPTION_MESSAGES_PROPERTIES";
@Autowired
private WebExceptionResponseHandler handler;
@Autowired
private MultipartProperties multipartProperties;
@Autowired
@Qualifier(EXCEPTION_MESSAGES_PROPERTIES_BEAN_NAME)
private Properties exceptionMessages;
private SimpleEvaluationContext context = new SimpleEvaluationContext.Builder(new ReflectivePropertyAccessor(), new MapAccessor()).build();
private SpelExpressionParser parser = new SpelExpressionParser();
@ExceptionHandler(AccessDeniedException.class)
public Object handleAuthorizationException(AccessDeniedException e) {
return handler.handle("没有权限,请联系管理员授权", e);
}
@ExceptionHandler(AccountExpiredException.class)
public Object handleAccountExpiredException(AccountExpiredException e) {
return handler.handle("登录失效了", e);
}
@ExceptionHandler(Exception.class)
public Object handleException(Exception e) {
String message = exceptionMessages.getProperty(e.getClass().getName());
if (StringUtils.isNotBlank(message)) {
if (message.contains("{")) {
message = (String) parser.parseExpression(message, new TemplateParserContext("{", "}")).getValue(context, e);
}
return handler.handle(message, e);
}
return handler.handle("系统错误", e);
}
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
public Object handleException(MethodArgumentTypeMismatchException e) {
String msg = String.format("参数类型错误: [%s] - %s 详细描述: %s", e.getName(),
e.getParameter().getParameterType().getSimpleName(),
e.getMessage()) ;
return handler.handle(msg, e);
}
/**
* query 参数的验证
* @param e
* @return
*/
@ExceptionHandler(ConstraintViolationException.class)
public Object handleException(ConstraintViolationException e) {
StringBuilder sb = new StringBuilder();
e.getConstraintViolations().forEach(o -> {
String fieldName = AlloyUtils.getFieldAlias(o);
sb.append(fieldName).append(" ").append(o.getMessage()).append("\n");
});
return handler.handle(sb.toString(), e);
}
@ExceptionHandler(BindException.class)
public Object validatedBindException(BindException e) {
String errorToString = AlloyUtils.getErrorToString(e);
return handler.handle(errorToString, e);
}
@ExceptionHandler(MissingRequestValueException.class)
public Object missingServletRequestParameterExceptionHandler(MissingRequestValueException e) {
String message;
if (e instanceof MissingServletRequestParameterException) {
MissingServletRequestParameterException e1 = (MissingServletRequestParameterException) e;
message = String.format("缺少query参数 [%s] ", e1.getParameterName());
} else {
message = e.getMessage();
}
return handler.handle(message, e);
}
@ExceptionHandler(MaxUploadSizeExceededException.class)
public Object maxUploadSizeExceededException(MaxUploadSizeExceededException e) {
long min = Math.min(multipartProperties.getMaxFileSize().toBytes(), multipartProperties.getMaxRequestSize().toBytes());
return handler.handle("文件最大支持:" + FileUtils.byteCountToDisplaySize(min), e);
}
@ExceptionHandler(HttpMessageNotReadableException.class)
public Object invalidFormatException(HttpMessageNotReadableException e) {
if (e.getCause() instanceof InvalidFormatException) {
InvalidFormatException cause = (InvalidFormatException) e.getCause();
String fieldPath = cause.getPath().stream().map(o -> o.getFieldName()).filter(o -> o != null).collect(Collectors.joining("."));
return handler.handle(String.format("%s 是 %s 类型,无法输入值为:%s", fieldPath, cause.getTargetType().getSimpleName(), cause.getValue().toString()), e);
}
return handler.handle(e.getMessage(), e);
}
}