Spring验证详解

目标: Spring自带的验证方式 基于JSR303的验证 国际化显示错误信息 一:使用Spring自带的验证方式 该种方式相对来说麻烦一点,需要为每个需要验证的实体类编写一个验证类,不过好处是可以处理多字段组合验证以及业务逻辑等复杂验证

1.1:定义实体类(User)

public class User {
 
    private String username;
 
    private String nickname;
 
    private String password;
 
   //省略getter /setter
}


1.2:定义实体类验证类(UserValidator) 需要继承Validator接口

public class UserValidator implements Validator {
 
    @Override
    public boolean supports(Class<?> clazz) {
        return User.class.equals(clazz);
    }
 
public void validate(Object target, Errors errors) {
       User user = (User)target;
        if(StringUtils.isEmpty(user.getUsername())){
            //1:使用这种方式,会报错(No message found under code 'empty.user.username.user.username' for locale 'zh_CN'.),因为rejectValue的第二个参数都是errorcode
            //errors.rejectValue("username","empty.user.username");
            //errors.rejectValue("username","用户名不能为空");
 
            //2:正确用法:rejectValue(String filed,String errorcode,Object[] errorArgs,String defaultMessage)
            errors.rejectValue("username","empty.user.username","用户名不能为空Default");
 
            //使用该种方式,不需要配置ResourceBundleMessageSource
           // ValidationUtils.rejectIfEmpty(errors,"username","empty.user.username","用户名不能为空");
        } else {
           int length =  user.getUsername().length();
            if(length<=3){
                errors.rejectValue("username","min.length.user.username","用户名长度不能小于3Default");
            }else if (length>=6){
                errors.rejectValue("username","max.length.user.username","用户名不能大于6Default");
            }
 
        }
        }
 
}


1.3:编写控制器代码:
@RequestMapping(value = "validatorBySpring", method = RequestMethod.GET)
   public String validatorBySpringForm(@ModelAttribute("user") User user) {
       return "validator/validatorBySpring";
   }
 
   /**
    * 第一种,使用spring自带的validator
    */
 
   @RequestMapping(value = "validatorBySpring", method = RequestMethod.POST)
   public String validatorBySpring(@ModelAttribute("user") User user,
                                   BindingResult result) {
       userValidator.validate(user, result);
       if (result.hasErrors()) {
           return "validator/validatorBySpring";
       }
       return "validator/success";
   }

注意:在get方法中,需要加上@ModelAttribute,否则无法访问,或者可以抽出来,写一个以下方法:

@ModelAttribute(“user")
public void getUser(){
     return new User();
}

这样的话,访问该控制器的时候都会调用该方法

1.4:前台

<form:form action="${ctx}/validator/validatorBySpring" method="post" modelattribute="user">
     
        <form:label path="username">Username</form:label>
        <form:input path="username"></form:input>
        <form:errors path="username"></form:errors>
       
         <form:label path="password">password</form:label> 
         <form:input path="password"></form:input>    
        <form:errors path="password"></form:errors>
     
         <form:label path="email">email</form:label> 
         <form:input path="email"></form:input>    
        <form:errors path="email"></form:errors>
        
            <input type="submit" value="SUBMIT">
         
</form:form>

1.5: 在上述代码已经可以完成Spring自带验证了,而且界面能正常显示错误信息,但是在实际过程中,错误信息采用的是硬编码,这是不可取的,所以,接下来需要国际化错误信息

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basename">
        <value>messages</value>
    </property>
</bean>

messages_zh_CN.properties 在resources/下 empty.user.username=用户名不能为空 min.length.user.username=用户名长度不能小于3 max.length.user.username=用户名长度不能大于6

其中的errorcode可以随便写,只要在messages中对应上即可,在这种情况下,在实体验证类中,就可以使用第一种方式即:errors.rejectValue(“username”,”empty.user.username)。因为在message文件中有对应的errorcode,所以能正常显示

扩展: 1:不使用rejectValue,而是使用reject,界面该如何显示 eg:errors.reject(“empty.user.username”,”用户名不能为空”); 直接在form中写如下:会显示全部错误

2:使用ValidationUtils ValidationUtils.rejectIfEmpty(errors,”username”,”empty.user.username”,”用户名不能为空”);

Errors主要使用方法:

reject(String errorcode,Object[] errorArgs,String defaultMessage)
 
rejectValue(String filed,String errorcode,Object[] errorArgs,String defaultMessage)
 
BinderResult接口扩展了Erros接口,以便可以使用Spring的Validator对对象进行校验,同时获取绑定结果对象的信息。

二:使用基于jsr303的验证 在Spring3.x企业开发实战里面提到:通过binder.setValidator之后,Spring MVC将使用它对入参对象进行校验,将不再使用Spring框架装配的Validator对入参进行校验。换句话说:即使在入参上标注了@Valid注解,也不会再根据入参对象类中的jsr303注解进行校验了。

2.1: 1:使用jsr303注解,可以注解基于javax.validator或者基于hibernated 。之前觉得没有什么不同,但是今天发现还是有不同的

2.1.1使用之前的配置,不做任何修改,messages里面没有任何对应的errorcode

@NotEmpty

起作用了,提示:may not be empty ,为什么会显示这个会有解释

@NotEmpty(message = "{username.not.empty}")

提示:{username.not.empty}

不起作用的原因是:NotNull和NotEmpty是不同滴。

@NotNull 并没有进行验证,而是直接通过,也就是验证没有起作用

@NotNull(message = “{username.not.empty}”) 仍然没有起作用

2.1.2:在资源文件中配置如下: username.not.empty=用户名不能为空1 @NotEmpty 显示 may not be empty

@NotEmpty(message = “{username.not.empty}”) 提示:{username.not.empty} 。即,直接显示message里面的内容,而我要的是显示:用户名不能为空1

2.1.3:在资源文件配置如下: username.not.empty=用户名不能为空1 NotNull.user.username=用户名不能为空 NotEmpty.user.username=用户名不能为空

@NotEmpty 提示:用户名不能为空

@NotEmpty(message = "{username.not.empty}”)   提示用户名不能为空,即:message里面的没有起作用,

去掉NotEmpty.user.username=用户名不能为空,则提示为{username.not.empty}


2.1.4:加上以上配置之后

<!-- 以下 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">
    </property></property></bean>


资源文件还是如下: username.not.empty=用户名不能为空1 NotNull.user.username=用户名不能为空 NotEmpty.user.username=用户名不能为空

注意,上面的并没有在mvc:annoation-driver中注册

@NotEmpty 提示用户名不能为空

@NotEmpty(message = “{username.not.empty}”)提示用户名不能为空,即messages仍然没有起作用

去掉NotEmpty.user.username=用户名不能为空,则提示为{username.not.empty}

@NotEmpty 提示用户名不能为空

@NotEmpty(message = “{username.not.empty}”)提示用户名不能为空,即messages仍然没有起作用

去掉NotEmpty.user.username=用户名不能为空,则提示为:用户名不能为空1

总结:因为不知道为什么基于javax.validator的注解不起作用,所以字总结基于hibernate的注解。这里一NotEmpty来举例。 首先,如果一旦在实体上标识了该注解,则就已经起作用了。如果不配置错误信息,将使用默认的:在hibernate-validator.jar中的Resource中,有一个ValidatorMessages.properties。里面有错误主力的默认显示:org.hibernate.validator.constraints.NotEmpty.message=may not be empty,这也就是为什么只配置了@NotEmpty之后显示 may not be empty的原因。当配置了自己的资源文件后,因为没有配置validator,所以还是显示之前的错误。那为什么后面没有配置validator。为什么NotEmpty.user.usrname能显示而{username.not.empty}不能正常显示呢?这是因为FileError实现了MessageResourceResolvable接口,里面有自己的一套规则: Annotation.entity.attribute。所以,我使用NotEmpty.user.username能显示中文,而使用{usrname.not.empty}却显示{username.not.empty}。在配置了validator之后,因为<mvc:annotaitonDriver 中没有指定validator,所以相当于没有配置。即:2.1.3的测试结果和2.1.4的测试结果一样。只有配置了 mvc:annotaiton-driver validator=“validator”之后,才能自定义错误格式,这种情况下才@NotEmpty{message={username.not.empty}}才能显示出来,不过NotEmpty.user.username这样格式的优先级比较高,两者放在一起,还是会显示后者。这就是,为什么在所有的一切都配置好之后,还是会显示“用户名不能为空”,只有在messages里面去掉之后才能显示username.not.empty的信息。

问题: 1:基于spring自带的validator前台不使用Spring form标签如何展示错误? 2:使用ajax方式,怎样进行验证,和上面是同样的问题,也就是不使用表单

其中,基于jsr303的可以实现,可以参考springside里面的代码,但是自带的却不好实现,因为循环FiledError的时候,只能得到errorcode和defultMessage,得不到国际化信息

资料: JSR 303 - Bean Validation 介绍及最佳实践 http://www.ibm.com/developerworks/cn/java/j-lo-jsr303/

开涛的博客:跟我学Spring mvc 3 http://jinnianshilongnian.iteye.com/blog/1617451

spring 3.x 企业开发实战



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值