背景

公司封装了自己的基础核心包core-base,里边包含了Validation的异常捕获处理类;同时开发项目有全局异常捕获处理类,经测试发现,core-base里边的不起作用

可能原因:

  1. 未扫描外部依赖包
  2. 标注@RestControllerAdvice的类,他们会依次加载,遇到异常时,按照类加载顺序进行判断,如果前面的类有能处理这个异常的方法,就给前面的类处理

解决

  1. 使用@ComponentScan()扫描
  2. 设置加载优先级,@Order注解标注或实现Ordered接口,重写getOrder()方法;
    @Order(Ordered.HIGHEST_PRECEDENCE) // order如果不标注数字,默认最低优先级,因为其默认值是int最大值

常用Validation异常处理配置

  • 多个参数校验时,默认返回所有的错误结果,如果只返回第一个校验失败的结果,可通过get(0)获取第一个,或者通过编写配置就可以实现
import com.dangbo.entity.ResultDTO;
import com.dangbo.enums.ResultCode;
import java.util.stream.Collectors;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ValidationExceptionHandler {
    @ExceptionHandler({MethodArgumentNotValidException.class})
    public ResultDTO MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
       List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
       String messages = fieldErrors.stream()
               .map(o -> o.getDefaultMessage())
               .collect(Collectors.joining(","));
       return ResultDTO.error(ResultCode.HTTP_INTERNAL_SERVER_ERROR, messages);
    }

    @ExceptionHandler({BindException.class})
    public ResultDTO BindExceptionHandler(BindException e) {
       List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
       // 多个参数校验时,默认返回所有的错误结果
       String messages = fieldErrors.stream()
               .map(o -> o.getDefaultMessage())
               .collect(Collectors.joining(","));
       return ResultDTO.error(ResultCode.HTTP_INTERNAL_SERVER_ERROR, messages);
    }

    @ExceptionHandler({ConstraintViolationException.class})
    public ResultDTO ConstraintViolationExceptionHandler(ConstraintViolationException e) {
       Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
       String messages = constraintViolations.stream()
               .map(o -> o.getMessage())
               .collect(Collectors.joining(","));
       return ResultDTO.error(ResultCode.HTTP_INTERNAL_SERVER_ERROR, messages);
    }
}

// 通用配置

import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;

import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

/**
 * validate参数校验默认的是一个参数校验失败后,还会继续校验后面的参数
 * 通过这个配置改成:校验参数时只要出现校验失败的情况,就立即抛出对应的异常,结束校验,不再进行后续的校验
 */
@Configuration
public class ValidationConfig {

    @Bean
    public Validator validator() {
        ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
                .configure()
                //failFast的意思只要出现校验失败的情况,就立即结束校验,不再进行后续的校验。
                .failFast(true)
                .buildValidatorFactory();
        return validatorFactory.getValidator();
    }

    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
        methodValidationPostProcessor.setValidator(validator());
        return methodValidationPostProcessor;
    }
}

参考:https://www.cnblogs.com/chongcheng/p/13058345.html