SpringBoot Service层使用Validate注解做接口参数校验

背景

使用注解参数校验,可避免业务代码中无休止的参数校验判断,在分层的方面来说,参数校验都是在Controller层完成的,那么Spring MVC中,可直接添加Validate相关的参数校验注解,即可快速完成而无需其它额外的配置,但是如果想在Service层的接口中添加参数校验,则需要额外的配置,否则,注解添加后是无效的。

实现

我们了解到参数校验是基于Validator来做的,首先需要添加hibernate-validator和validation-api依赖,由于spring-boot-starter-web依赖hibernate-validator,而hibernate-validate又依赖validation-api,所以项目中只需要添加spring-boot-starter-web依赖即可,如下:


	org.springframework.boot
	spring-boot-starter-web
	2.1.1.RELEASE

此时,需要在切面中通过Validator完成接口调用时的参数校验,实现如下:

@Aspect
@Component
public class ParamsCheckAspect {
    
    private static Validator validator;
    static {
        validator = Validation.byDefaultProvider().configure()
                .messageInterpolator(new ResourceBundleMessageInterpolator(
				new PlatformResourceBundleLocator("validationMessages"))) //手动指定校验提示资源(默认在resource目录下ValidationMessages.properties)
                .buildValidatorFactory().getValidator();
    }

    // 定义接口参数校验切入点
    @Pointcut("@annotation(org.springframework.validation.annotation.Validated))")
    private void validateMethod() {
    }
    
    @Before("validateMethod()")
    public void before(JoinPoint joinPoint) throws CheckedException {
        Object[] args = joinPoint.getArgs();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		// 执行方法参数的校验
        Set> constraintViolations = validator.forExecutables().validateParameters(joinPoint.getThis(), signature.getMethod(), args);
        List messages = Lists.newArrayList();
        for (ConstraintViolation error : constraintViolations) {
            messages.add(error.getMessage());
        }
        if(!messages.isEmpty()){
            throw new CheckedException(JSONObject.toJSONString(messages));
        }
    }
    
} 
  

代码解析:

  1. 在static块中,完成Validator的初始化;
  2. validateMethod是定义切点,通过PointCut注解可以看出,只有添加了Validated注解的方法被调用时,才会执行参数校验,此举是为了减少没有参数校验注解的方法也要执行校验的过程,避免性能浪费。
  3. 由于参数校验要先于方法的执行,所以,通过Before注解,执行前置执行,在该切面方法中完成参数的校验。

使用示例

在完成校验的逻辑后,接下来就是使用示例,使用时需要注册基本参数注解校验和POJO类型的参数校验,需要校验POJO时,需要添加Valid注解,其它的基本参数注解则正常使用即可,如下:

@Validate
public int saveUser(@Min(value=1, message="{a.b.c}") int operUserId, 
					@NotNull(message = "{x.y.z}") @Valid User user);

 代码解析:

  1. 首先方法实现需要添加@Validate注解,否则,上一步中配置的切面不会被执行,从而也不会进行参数校验;
  2. 示例中分为基本参数校验和POJO校验,需要注意的是message注解属性的格式,这里硬编码也可以,但是使用占位符的方式更加方便配置和复用,此处a.b.c和x.y.z需要在上一步的validationMessages中定义好;
  3. 需要注意的是POJO需要额外添加@Valid注解,才能对POJO中的属性进行校验;
  4. 特别注意:1中的注解要写在实现类上,2、3中的注解需要写在接口上,实现类中写不写都可以,否则会出错,错误可自行研究。

你可能感兴趣的:(Java,Spring系列,SpringBoot)