All Downloads are FREE. Search and download functionalities are using the official Maven repository.

matrix.boot.based.config.ResultControllerExceptionAutoConfiguration Maven / Gradle / Ivy

There is a newer version: 2.1.10
Show newest version
package matrix.boot.based.config;

import lombok.extern.slf4j.Slf4j;
import matrix.boot.based.properties.ResultControllerExceptionProperties;
import matrix.boot.based.utils.I18nMessageUtil;
import matrix.boot.common.dto.Result;
import matrix.boot.common.exception.*;
import matrix.boot.common.utils.StringUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.core.PriorityOrdered;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Result Controller异常捕捉器
 *
 * @author wangcheng
 */
@EnableConfigurationProperties(ResultControllerExceptionProperties.class)
@ConditionalOnProperty(value = {"matrix.exception.enabled"}, matchIfMissing = true)
@RestControllerAdvice
@Slf4j
public class ResultControllerExceptionAutoConfiguration {

    /**
     * 全局异常配置
     */
    private final ResultControllerExceptionProperties resultControllerExceptionProperties;

    public ResultControllerExceptionAutoConfiguration(ResultControllerExceptionProperties resultControllerExceptionProperties) {
        this.resultControllerExceptionProperties = resultControllerExceptionProperties;
    }

    /**
     * 捕捉ResultControllerException
     *
     * @param req  请求体
     * @param resp 返回体
     * @param e    异常信息
     * @return Result包装信息
     */
    @ExceptionHandler({ResultControllerException.class})
    @ResponseStatus(code = HttpStatus.OK)
    @ResponseBody
    public Result defaultHandler(HttpServletRequest req, HttpServletResponse resp, Exception e) {
        Throwable throwable = e.getCause();
        //默认的错误编码
        Integer defaultErrorCode = resultControllerExceptionProperties.getDefaultErrorCode();
        if (throwable == null) {
            return Result.fail("forbidden throw ResultControllerException!", defaultErrorCode);
        }
        while (throwable instanceof ResultControllerException && throwable.getCause() != null) {
            throwable = throwable.getCause();
        }
        if (throwable instanceof ConstraintViolationException) {
            //内部异常校验
            ConstraintViolationException ex = (ConstraintViolationException) throwable;
            log.error(ex.getConstraintViolations().stream().map(item -> item.getRootBeanClass().getName() + "." + item.getPropertyPath().toString() + ":" + item.getMessage()).collect(Collectors.joining("|")));
            return Result.fail("params error").setErrorCode(resultControllerExceptionProperties.getDefaultErrorCode());
        }
        if (throwable instanceof BusinessException) {
            //business异常不打印堆栈信息
            BusinessException businessException = (BusinessException) throwable;
            log.error("business exception: message: {}", businessException.getMessage());
            return Result.fail(throwable.getMessage()).setErrorCode(businessException.getErrorCode() == null ? defaultErrorCode : businessException.getErrorCode());
        }
        if (throwable instanceof I18nBusinessException) {
            //国际化business 异常不打印堆栈信息
            I18nBusinessException businessException = (I18nBusinessException) throwable;
            //获取国际化的消息
            String message = I18nMessageUtil.get(businessException.getMessageCode());
            log.error("i18n business exception message code: {}, value: {}, message: {}", businessException.getMessageCode(), message, businessException.getMessage());
            String resultMessage = StringUtil.isEmpty(message) ? businessException.getMessage() : message;
            return Result.fail(resultMessage).setErrorCode(businessException.getErrorCode() == null ? defaultErrorCode : businessException.getErrorCode());
        }
        if (throwable instanceof ServiceException) {
            //service异常
            log.error(throwable.getMessage(), throwable);
            ServiceException serviceException = (ServiceException) throwable;
            return Result.fail(throwable.getMessage()).setErrorCode(serviceException.getErrorCode() == null ? defaultErrorCode : serviceException.getErrorCode());
        }
        if (throwable instanceof I18nServiceException) {
            //国际化service异常
            log.error(throwable.getMessage(), throwable);
            I18nServiceException serviceException = (I18nServiceException) throwable;
            //获取国际化的消息
            String message = I18nMessageUtil.get(serviceException.getMessageCode());
            String resultMessage = StringUtil.isEmpty(message) ? throwable.getMessage() : message;
            return Result.fail(resultMessage).setErrorCode(serviceException.getErrorCode() == null ? defaultErrorCode : serviceException.getErrorCode());
        }
        //其他异常
        log.error(throwable.getMessage(), throwable);
        return Result.fail(throwable.getMessage()).setErrorCode(resultControllerExceptionProperties.getDefaultErrorCode());
    }

    /**
     * 捕捉校验参数的异常
     *
     * @param ex 异常数据
     * @return 校验参数的异常
     */
    @ExceptionHandler(BindException.class)
    @ResponseStatus(code = HttpStatus.OK)
    @ResponseBody
    public Result defaultHandler(BindException ex) {
        String result = parseErrorMessage(ex.getBindingResult().getAllErrors());
        log.error(result);
        return Result.fail("params error").setErrorCode(resultControllerExceptionProperties.getDefaultErrorCode());
    }

    /**
     * 切面,针对所有返回为result的controller的错误包装为ResultControllerException抛出
     */
    @EnableConfigurationProperties(ResultControllerExceptionProperties.class)
    @ConditionalOnProperty(value = {"matrix.exception.enabled"}, matchIfMissing = true)
    @Aspect
    public static class ResultControllerAspect implements PriorityOrdered {

        @Pointcut("execution(matrix.boot.common.dto.Result||reactor.core.publisher.Mono||reactor.core.publisher.Flux *(..))")
        public void result() {
        }

        @Around("result()")
        public Object resultAround(ProceedingJoinPoint joinPoint) {
            try {
                return joinPoint.proceed(joinPoint.getArgs());
            } catch (Throwable e) {
                throw new ResultControllerException(e);
            }
        }

        @Override
        public int getOrder() {
            return 0;
        }
    }

    /**
     * 解析错误信息
     *
     * @param objectErrors 对象错误信息
     * @return 错误信息
     */
    private static String parseErrorMessage(List objectErrors) {
        List errorMessages = new ArrayList<>();
        for (ObjectError objectError : objectErrors) {
            if (objectError instanceof FieldError) {
                FieldError fieldError = (FieldError) objectError;
                errorMessages.add(fieldError.getObjectName() + "." + fieldError.getField() + ":" + fieldError.getDefaultMessage());
            } else {
                errorMessages.add(objectError.getObjectName() + ":" + objectError.getDefaultMessage());
            }
        }
        return String.join("|", errorMessages);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy