javaxvalidation--参数基础校验
Bean Validation 1.1当前实现是 validator 5,且spring4才⽀持。接下来我们从以下⼏个⽅法讲解Bean Validation 1.1,当然不⼀定是新特性:
1. 集成Bean Validation 1.1到SpringMVC
2. 分组验证、分组顺序及级联验证
3. 消息中使⽤EL表达式
4. ⽅法参数/返回值验证
5. ⾃定义验证规则
6. 类级别验证器
7. 脚本验证器
8.  cross-parameter,跨参数验证
9. 混合类级别验证器和跨参数验证器
10. 组合多个验证注解
11. 本地化
因为⼤多数时候验证都配合web框架使⽤,⽽且很多朋友都咨询过如分组/跨参数验证,所以本⽂介绍下这些,且是和SpringMVC框架集成的例⼦,其他使⽤⽅式(⽐如集成到JPA中)可以参考其官⽅⽂档:
1、集成Bean Validation 1.1到SpringMVC
1.1、项⽬搭建
⾸先添加hibernate validator 5依赖:
Java代码
01. <dependency>
02.    <groupId>org.hibernate</groupId>
03.    <artifactId>hibernate-validator</artifactId>
04.    <version>5.0.2.Final</version>
05. </dependency>
如果想在消息中使⽤EL表达式,请确保EL表达式版本是 2.2或以上,如使⽤Tomcat6,请到Tomcat7中拷贝相应的EL jar包到Tomcat6中。
Java代码
01. <dependency>
02.    <groupId>javax.el</groupId>
03.    <artifactId>javax.el-api</artifactId>
04.    <version>2.2.4</version>
05.    <scope>provided</scope>
validation框架06. </dependency>
请确保您使⽤的Web容器有相应版本的el jar包。
对于其他POM依赖请下载附件中的项⽬参考。
1.2、 MVC配置⽂件(l):
01. <!-- 指定⾃⼰定义的validator -->
02. <mvc:annotation-driven validator="validator"/>
03.
04. <!-- 以下 validator  ConversionService 在使⽤ mvc:annotation-driven 会⾃动注册-->
05. <bean id="validator"class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
06.    <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
07.    <!-- 如果不加默认到使⽤classpath下的 ValidationMessages.properties -->
08.    <property name="validationMessageSource" ref="messageSource"/>
09. </bean>
10.
11. <!-- 国际化的消息资源⽂件(本系统中主要⽤于显⽰/错误消息定制) -->
12. <bean id="messageSource"class="t.support.ReloadableResourceBundleMessageSou
rce">
13.    <property name="basenames">
14.        <list>
15.            <!-- 在web环境中⼀定要定位到classpath 否则默认到当前web应⽤下  -->
16.            <value>classpath:messages</value>
17.            <value>classpath:org/hibernate/validator/ValidationMessages</value>
18.        </list>
19.    </property>
20.    <property name="useCodeAsDefaultMessage" value="false"/>
21.    <property name="defaultEncoding" value="UTF-8"/>
22.    <property name="cacheSeconds" value="60"/>
23. </bean>
此处主要把bean validation的消息查委托给spring的messageSource。
1.3、实体验证注解:
Java代码
01. public class User implements Serializable {
02. @NotNull(message = "{user.id.null}")
03. private Long id;
04.
05. @NotEmpty(message = "{user.name.null}")
06. @Length(min = 5, max = 20, message = "{user.name.length.illegal}")
07. @Pattern(regexp = "[a-zA-Z]{5,20}", message = "{user.name.illegal}")
08. private String name;
09.
10. @NotNull(message = "{user.password.null}")
11. private String password;
12. }
对于验证规则可以参考官⽅⽂档,或者《》。
1.4、错误消息⽂件messages.properties:
Java代码
01. user.id.null=⽤户编号不能为空
02. user.name.null=⽤户名不能为空
03. user.name.length.illegal=⽤户名长度必须在5到20之间
04. user.name.illegal=⽤户名必须是字母
05. user.password.null=密码不能为空
1.5、控制器
Java代码
01. @Controller
02. public class UserController {
03.
04. @RequestMapping("/save")
05. public String save(@Valid User user, BindingResult result) {
06. if(result.hasErrors()) {
07. return"error";
08.        }
09. return"success";
10.    }
11. }
1.6、错误页⾯:
01. <spring:hasBindErrors name="user">
02.    <c:if test="${errors.fieldErrorCount > 0}">
03. 字段错误:<br/>
04.        <c:forEach items="${errors.fieldErrors}" var="error">
05.            <spring:message var="message" code="${de}" arguments="${error.arguments}" text="${error.default
Message}"/>
06.            ${error.field}------${message}<br/>
07.        </c:forEach>
08.    </c:if>
09.
10.    <c:if test="${errors.globalErrorCount > 0}">
11. 全局错误:<br/>
12.        <c:forEach items="${errors.globalErrors}" var="error">
13.            <spring:message var="message" code="${de}" arguments="${error.arguments}" text="${error.default
Message}"/>
14.            <c:if test="${not empty message}">
15.                ${message}<br/>
16.            </c:if>
17.        </c:forEach>
18.    </c:if>
19. </spring:hasBindErrors>
⼤家以后可以根据这个做通⽤的错误消息显⽰规则。⽐如我前端页⾯使⽤validationEngine显⽰错误消息,那么我可以定义⼀个tag来通⽤化错误消息的显⽰:。
1.7、
Java代码
01. name------⽤户名必须是字母
02. name------⽤户名长度必须在5到20之间
03. password------密码不能为空
04. id------⽤户编号不能为空
基本的集成就完成了。
如上测试有⼏个⼩问题:
1、错误消息顺序,⼤家可以看到name的错误消息顺序不是按照书写顺序的,即不确定;
2、我想显⽰如:⽤户名【zhangsan】必须在5到20之间;其中我们想动态显⽰:⽤户名、min,max;⽽不是写死了;
3、我想在修改的时候只验证⽤户名,其他的不验证怎么办。
接下来我们挨着试试吧。
2、分组验证及分组顺序
如果我们想在新增的情况验证id和name,⽽修改的情况验证name和password,怎么办?那么就需要分组了。
⾸先定义分组接⼝:
Java代码
01. public interface First {
02. }
03.
04. public interface Second {
05. }
分组接⼝就是两个普通的接⼝,⽤于标识,类似于.io.Serializable。
接着我们使⽤分组接⼝标识实体:
01. public class User implements Serializable {
02.
03. @NotNull(message = "{user.id.null}", groups = {First.class})
04. private Long id;
05.
06. @Length(min = 5, max = 20, message = "{user.name.length.illegal}", groups = {Second.class})
07. @Pattern(regexp = "[a-zA-Z]{5,20}", message = "{user.name.illegal}", groups = {Second.class})
08. private String name;
09.
10. @NotNull(message = "{user.password.null}", groups = {First.class, Second.class})
11. private String password;
12. }
验证时使⽤如:
Java代码
01. @RequestMapping("/save")
02. public String save(@Validated({Second.class}) User user, BindingResult result) {
03. if(result.hasErrors()) {
04. return"error";
05.    }
06. return"success";
07. }
即通过@Validate注解标识要验证的分组;如果要验证两个的话,可以这样@Validated({First.class, Second.class})。
接下来我们来看看通过分组来指定顺序;还记得之前的错误消息吗? user.name会显⽰两个错误消息,⽽且顺序不确定;如果我们先验证⼀个消息;如果不通过再验证另⼀个怎么办?可以通过@GroupSequence指定分组验证顺序:
Java代码
01. @GroupSequence({First.class, Second.class, User.class})
02. public class User implements Serializable {
03. private Long id;
04.
05. @Length(min = 5, max = 20, message = "{user.name.length.illegal}", groups = {First.class})
06. @Pattern(regexp = "[a-zA-Z]{5,20}", message = "{user.name.illegal}", groups = {Second.class})
07. private String name;
08.
09. private String password;
10. }
通过@GroupSequence指定验证顺序:先验证First分组,如果有错误⽴即返回⽽不会验证Second分组,接着如果First分组验证通过了,那么才去验证Second分组,最后指定User.class表⽰那些没有分组的在最后。这样我们就可以实现按顺序验证分组了。
另⼀个⽐较常见的就是级联验证:
如:
Java代码
01. public class User {
02.
03. @Valid
04. @ConvertGroup(from=First.class, to=Second.class)
05. private Organization o;
06.
07. }
1、级联验证只要在相应的字段上加@Valid即可,会进⾏级联验证;@ConvertGroup的作⽤是当验证o的分组是First时,那么验证o的分组是Second,即分组验证的转换。
3、消息中使⽤EL表达式
假设我们需要显⽰如:⽤户名[NAME]长度必须在[MIN]到[MAX]之间,此处⼤家可以看到,我们不想把⼀些数据写死,如NAME、MIN、MAX;此时我们可以使⽤EL表达式。
如:
01. @Length(min = 5, max = 20, message = "{user.name.length.illegal}", groups = {First.class})
错误消息:
Java代码
01. user.name.length.illegal=⽤户名长度必须在{min}到{max}之间
其中我们可以使⽤{验证注解的属性}得到这些值;如{min}得到@Length中的min值;其他的也是类似的。
到此,我们还是⽆法得到出错的那个输⼊值,如name=zhangsan。此时就需要EL表达式的⽀持,⾸先确定引⼊EL jar包且版本正确。然后使⽤如:
Java代码
01. user.name.length.illegal=⽤户名[${validatedValue}]长度必须在5到20之间
使⽤如EL表达式:${validatedValue}得到输⼊的值,如zhangsan。当然我们还可以使⽤如${min > 1 ? '⼤于1' : '⼩于等于1'},及在EL表达式中也能拿到如@Length的min等数据。
另外我们还可以拿到⼀个java.util.Formatter类型的formatter变量进⾏格式化:
Java代码
01. ${formatter.format("%04d", min)}
4、⽅法参数/返回值验证
这个可以参考《》,概念是类似的,具体可以参考Bean Validation ⽂档。
5、⾃定义验证规则
有时候默认的规则可能还不够,有时候还需要⾃定义规则,⽐如屏蔽关键词验证是⾮常常见的⼀个功能,⽐如在发帖时帖⼦中不允许出现admin等关键词。
1、定义验证注解

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。