SpringMVC验证框架Validation特殊用法

基本用法不说了,网上例子不少,这里主要介绍下比较特殊状况下使用的方法。java

1. 分组web

有的时候,咱们对一个实体类须要有多中验证方式,在不一样的状况下使用不一样验证方式,好比说对于一个实体类来的id来讲,保存的时候是不须要的,对于更新时是必须的,能够以下配置:spring

public class UserModel {

    @NotNull(message = "{id.empty}", groups = {First.class})
    private int id;
    @NotNull(message = "{username.empty}", groups = {First.class, Second.class})
    private String username;
    @NotNull(message = "{content.empty}", groups = {First.class, Second.class})
    private String content;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

public interface First {}
public interface Second {}

经过 groups 对验证进行分组spring-mvc

在controler中的代码以下:mvc

@RequestMapping(value = "/save.action", method = RequestMethod.POST)
public String save(@Validated({Second.class}) UserModel userModel, BindingResult result) {
    if (result.hasErrors()) {
        return "validate/error";
    }
    return "redirect:/success";
}

@RequestMapping(value = "/update.action", method = RequestMethod.POST)
public String update(@Validated({First.class, Second.class}) UserModel user, BindingResult result) {
    if (result.hasErrors()) {
        return "validate/error";
    }
    return "redirect:/success";
}

2. 组序列app

默认状况下,不一样组别的约束验证是无序的,然而在某些状况下,约束验证的顺序却很重要,以下面两个例子:(1)第二个组中的约束验证依赖于一个稳定状态来运行,而这个稳定状态是由第一个组来进行验证的。(2)某个组的验证比较耗时,CPU 和内存的使用率相对比较大,最优的选择是将其放在最后进行验证。所以,在进行组验证的时候尚需提供一种有序的验证方式,这就提出了组序列的概念。ide

一个组能够定义为其余组的序列,使用它进行验证的时候必须符合该序列规定的顺序。在使用组序列验证的时候,若是序列前边的组验证失败,则后面的组将再也不给予验证。测试

下例中声明了组 GroupA.class,GroupB.class 和 Group.class,其中 default,GroupA,GroupB 均为 Group 的序列。this

public interface GroupA {}
public interface GroupB {}

@GroupSequence({Default.class, GroupA.class, GroupB.class})
public interface Group {}

public class User {

    @NotEmpty(message = "firstname may be empty")
    private String firstname;
    @NotEmpty(message = "middlename may be empty", groups = Default.class)
    private String middlename;
    @NotEmpty(message = "lastname may be empty", groups = GroupA.class)
    private String lastname;
    @NotEmpty(message = "country may be empty", groups = GroupB.class)
    private String country;
}

3. 验证多个对象spa

当咱们在一个功能处理方法上须要验证多个模型对象时,须要经过以下形式来获取验证结果:

@RequestMapping("/validate/multi")
public String multi(@Valid @ModelAttribute("a") A a, BindingResult aErrors, @Valid @ModelAttribute("b") B b, BindingResult bErrors) {
    if (aErrors.hasErrors()) { //若是a模型对象验证失败  
        return "validate/error";
    }
    if (bErrors.hasErrors()) { //若是a模型对象验证失败  
        return "validate/error";
    }
    return "redirect:/success";
}

每个模型对象后边都须要跟一个Errors或BindingResult对象来保存验证结果,其方法体内部可使用这两个验证结果对象来选择出错时跳转的页面或处理的逻辑。

4. Junit测试

当自定义拓展Validation时,可使用以下方法进行测试:

@Test
public void testValidate() {
    AnnotationDescriptor<EqualsAny> descriptor = new AnnotationDescriptor<EqualsAny>(EqualsAny.class);
    EqualsAny equalsAny = AnnotationFactory.create(descriptor);
    EqualsAnyValidator equalsAnyValidator = new EqualsAnyValidator();
    equalsAnyValidator.initialize(equalsAny);
    Assert.assertTrue(equalsAnyValidator.isValid("123", null));
}

另外再讲一点Spring对自定义JSR-303限制类型支持的新特性,那就是Spring支持往ConstraintValidator里面注入bean对象。例如在EqualsAnyValidator中利用@Resource注解注入其余Bean对象。

补充:

Spring MVC配置文件(spring-mvc.xml)

<!-- 指定本身定义的validator -->
<mvc:annotation-driven validator="validator"/>
<!-- 如下 validator  ConversionService 在使用 mvc:annotation-driven 会 自动注册-->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
<!-- 若是不加默认到 使用classpath下的 ValidationMessages.properties -->
<property name="validationMessageSource" ref="messageSource"/>
</bean>
<!-- 国际化的消息资源文件(本系统中主要用于显示/错误消息定制) -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
    <list>
        <!-- 在web环境中必定要定位到classpath 不然默认到当前web应用下找  -->
        <value>classpath:messages</value>
        <value>classpath:org/hibernate/validator/ValidationMessages</value>
    </list>
</property>
<property name="useCodeAsDefaultMessage" value="false"/>
<property name="defaultEncoding" value="UTF-8"/>
<property name="cacheSeconds" value="60"/>
</bean>  

此处主要把bean validation的消息查找委托给spring的messageSource。

错误消息文件messages.properties:

user.id.null=用户编号不能为空  
user.name.null=用户名不能为空  
user.name.length.illegal=用户名长度必须在5到20之间  
user.name.illegal=用户名必须是字母  
user.password.null=密码不能为空  

消息中使用EL表达式

假设咱们须要显示如:用户名[NAME]长度必须在[MIN]到[MAX]之间,此处你们能够看到,咱们不想把一些数据写死,如NAME、MIN、MAX;此时咱们可使用EL表达式。

@Length(min = 5, max = 20, message = "{user.name.length.illegal}", groups = {First.class})

错误消息:

user.name.length.illegal=用户名长度必须在{min}到{max}之间

使用如EL表达式:${validatedValue}获得输入的值 :

user.name.length.illegal=用户名[${validatedValue}]长度必须在{min}到{max}之间

另外咱们还能够拿到一个java.util.Formatter类型的formatter变量进行格式化:

${formatter.format("%04d", min)}
相关文章
相关标签/搜索