Spring 3 对JSR-303/JSR-349的验证支持

本文介绍了如何在 Spring MVC 应用中使用 JSR-303 进行数据验证,包括自定义验证注解、配置验证提供者以及方法级验证等实践案例。

Sring 3 完全支持JSR-303 Bean的验证API,当编程使用验证时,Spring的DataBinder可以验证对象并绑定他们,最后Spring MVC现在支持在@COntroller中输入验证内容。

例子:

1.编写VO对象并设置验证规则

package com.test.entity.vo;

import lombok.Data;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

/**
 * @Author:qmfang
 * @Description:
 * @Date:Created in 12:21 2018/4/11
 * @Modified By:
 */
@Data
public class MyModel {

    @NotNull
    @Size(max=64)
    private String name;

    @Min(0)
    private int age;
}

2.配置bean Validation提供者 Spring boot好像默认就提供了,不需要此步骤

    /**
     *
     * 触发bean验证使用默认的引导机制进行初始化
     * JSR-303/JSR-349提供程序(如Hibernate-Validator)需要放到类路径下,
     * 以便能被自动检测。
     *
     * @return
     */
    @Bean
    public LocalValidatorFactoryBean validator() {
        return new LocalValidatorFactoryBean();
    }

3.创建验证类

@Service
public class MyService {

    @Autowired
    private Validator validator;

    public <T> void validate(T entity, Class<?>... groups) {
        Set<ConstraintViolation<T>> constraintViolations = validator.validate(entity, groups);
        if (constraintViolations.isEmpty()) {
            return;
        }
        ConstraintViolation<T> first = constraintViolations.iterator().next();
        throw new RuntimeException(first.getMessage());
    }
}

4.对VO对象进行校验

    @Autowired
    private MyService myService;
    /**
     * 127.0.0.1:8886/get3?name=shijieheping&age=-1
     *
     * @return
     */
    @GetMapping(value = "/get3")
    public Object get(MyModel myModel) throws IOException {
        myService.validate(myModel);
        return myModel;
    }

这样使用起来有点麻烦,需要注入校验对象,采用如下形式会跟方便一点。这样使用时就不需要在使用注入的形式了,同时也可以去掉步骤2.配置bean Validation提供者 因为下面的类在static{}快中自行构建了

public class MyService {

    private static final Validator validator;

    static {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        validator = factory.getValidator();
    }


    public static <T> void validate(T entity, Class<?>... groups) {
        Set<ConstraintViolation<T>> constraintViolations = validator.validate(entity, groups);
        if (constraintViolations.isEmpty()) {
            return;
        }
        ConstraintViolation<T> first = constraintViolations.iterator().next();
        throw new RuntimeException(first.getMessage());
    }

}

配置自定义约束

每个bean验证约束都由两部分组成,首先是申明约束及其可配置的@Constraint注解,然后是实现约束行为的javax.validation.ConstraintValidator接口实现,如果要将声明与实现关联,每个@Constraint注解都会应用相应的ValidationConstranit实现类,在运行中,当在域模型中遇到约束注解时,ConstranitValidatorFactory会将应用的实现实例化。

默认情况下,LocalValidatorFactoryBean会配置SpringConstraintValidatorFactory,他会使用Spring去创建ConstranitValidator实例,这允许自定义ConstranitValidators,就像任何其他Spring Bean一样,从依赖注入中获利。

1.编写相应的注解 以及校验实现类  注意就是NameCheck时可以在外部定义,通过@Component 来使用@Autowried注解的

import org.springframework.util.StringUtils;

import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.*;

/**
 * @Author:qmfang
 * @Description:
 * @Date:Created in 15:10 2018/4/11
 * @Modified By:
 */
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {Name.NameCheck.class})
public @interface Name {

    /**
     * 使用该消息进行提示
     *
     * @return
     */
    String message() default "名字不能为空";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    class NameCheck implements ConstraintValidator<Name, String> {

        @Override
        public void initialize(Name name) {

        }

        @Override
        public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
            return StringUtils.isEmpty(s);
        }
    }
}

2.编写测试用例

import com.test.config.Name;
import lombok.Data;
import javax.validation.constraints.Min;

/**
 * @Author:qmfang
 * @Description:
 * @Date:Created in 12:21 2018/4/11
 * @Modified By:
 */
@Data
public class MyModel {

    @Name
    private String name;

    @Min(0)
    private int age;
}
   @GetMapping(value = "/get3")
    public Object get(MyModel myModel) throws IOException {
        MyService.validate(myModel);
        return myModel;
    }
即可。


Spring 驱动的方法验证

Bean Validation1.1支持方法验证 Hibernate Validator 4.3支持的自定义扩展也可以通过MethodValidationPostProcessor bean定义继承到Spring上下文中。

Spring  boot默认的注册了MethodValidationPostProcessor 

当然也可以手动注册,已追加扩展

    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        return new MethodValidationPostProcessor();
    }

然后在类上使用@Validated注解如下

@Validated
@RestController
public class TestController {

    /**
     * 127.0.0.1:8886/get3?name=shijieheping&age=-1
     *
     * @return
     */
    @GetMapping(value = "/get3")
    public Object get(@Length(min = 10) String name) throws IOException {
        System.out.println(name);
        return name;
    }

}

这样就可以针对单个参数进行校验了。注意点就是 此注解对于非controller类的方法没有效果。


配置DataBinder

从Spring 3开始,可以使用Validator配置DataBinder实例,配置后,可以通过调用binder.validate()方法使用,任何验证错误都可以自动加入到binder的BindingResult中。

在以编程的方式使用DataBinder时,可以在绑定到目标对象后调用验证逻辑。

DataBinder还可以通过DataBinderaddValidators和replaceValidators来配置多个Validator实例,将全局配置的Bean Validation与本地在DataBinder实例上配置的Spring Validator相结合,能够发挥强大的威力。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值