注意:1 public String save(@ModelAttribute("house") @Valid House entity, BindingResult result,HttpServletRequest request,  Model model)     BindingResult 必须放在model,request前面

   2 validation-api-1.0.0.GA.jar是JDK的接口;hibernate-validator-4.2.0.Final.jar是对上述接口的实现。hibernate-validator-4.2.0.Final可以,但是hibernate-validator-4.3.0.Final报错

验证注解

验证的数据类型

说明

@AssertFalse

Boolean,boolean

验证注解的元素值是false

@AssertTrue

Boolean,boolean

验证注解的元素值是true

@NotNull

任意类型

验证注解的元素值不是null

@Null

任意类型

验证注解的元素值是null

@Min(value=值)

BigDecimal,BigInteger, byte,

short, int, long,等任何Number或CharSequence(存储的是数字)子类型

验证注解的元素值大于等于@Min指定的value值

@Max(value=值)

和@Min要求一样

验证注解的元素值小于等于@Max指定的value值

@DecimalMin(value=值)

和@Min要求一样

验证注解的元素值大于等于@ DecimalMin指定的value值

@DecimalMax(value=值)

和@Min要求一样

验证注解的元素值小于等于@ DecimalMax指定的value值

@Digits(integer=整数位数, fraction=小数位数)

和@Min要求一样

验证注解的元素值的整数位数和小数位数上限

@Size(min=下限, max=上限)

字符串、Collection、Map、数组等

验证注解的元素值的在min和max(包含)指定区间之内,如字符长度、集合大小

@Past

java.util.Date,

java.util.Calendar;

Joda Time类库的日期类型

验证注解的元素值(日期类型)比当前时间早

@Future

与@Past要求一样

验证注解的元素值(日期类型)比当前时间晚

@NotBlank

CharSequence子类型

验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的首位空格

@Length(min=下限, max=上限)

CharSequence子类型

验证注解的元素值长度在min和max区间内

@NotEmpty

CharSequence子类型、Collection、Map、数组

验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)

@Range(min=最小值, max=最大值)

BigDecimal,BigInteger,CharSequence, byte, short, int, long等原子类型和包装类型

验证注解的元素值在最小值和最大值之间

@Email(regexp=正则表达式,

flag=标志的模式)

CharSequence子类型(如String)

验证注解的元素值是Email,也可以通过regexp和flag指定自定义的email格式

@Pattern(regexp=正则表达式,

flag=标志的模式)

String,任何CharSequence的子类型

验证注解的元素值与指定的正则表达式匹配

@Valid

任何非原子类型

指定递归验证关联的对象;

如用户对象中有个地址对象属性,如果想在验证用户对象时一起验证地址对象的话,在地址对象上加@Valid注解即可级联验证

一、准备校验时使用的JAR

说明:

validation-api-1.0.0.GA.jar是JDK的接口;

hibernate-validator-4.2.0.Final.jar是对上述接口的实现。

------------------------------------------------------------------------------------------------

新增一个测试的pojo bean ,增加jsr 303格式的验证annotation

  1. @NotEmpty
  2. private String userName;
  3. @Email
  4. private String email;

在controller 类中的handler method中,对需要验证的对象前增加@Valid 标志

  1. @RequestMapping("/valid")
  2. public String valid(@ModelAttribute("vm") [color=red]@Valid[/color] ValidModel vm, BindingResult result) {
  3. if (result.hasErrors()) {
  4. return "validResult";
  5. }
  6. return "helloworld";
  7. }

增加显示验证结果的jsp如下

  1. <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
  2. <html>
  3. <head>
  4. <title>Reservation Form</title>
  5. <style>
  6. .error {
  7. color: #ff0000;
  8. font-weight: bold;
  9. }
  10. </style>
  11. </head>
  12. <body>
  13. <form:form method="post" modelAttribute="vm">
  14. <form:errors path="*" cssClass="error" />
  15. <table>
  16. <tr>
  17. <td>Name</td>
  18. <td><form:input path="userName" />
  19. </td>
  20. <td><form:errors path="userName" cssClass="error" />
  21. </td>
  22. </tr>
  23. <tr>
  24. <td>email</td>
  25. <td><form:input path="email" />
  26. </td>
  27. <td><form:errors path="email" cssClass="error" />
  28. </td>
  29. </tr>
  30. <tr>
  31. <td colspan="3"><input type="submit" />
  32. </td>
  33. </tr>
  34. </table>
  35. </form:form>
  36. </body>
  37. </html>

访问 http://localhost:8080/springmvc/valid?userName=winzip&email=winzip 
查看验证结果。 
二:自定义jsr 303格式的annotation 
参考hibernate validator 4 reference 手册中3.1节,增加一个自定义要求输入内容为定长的annotation验证类 
新增annotation类定义

  1. @Target( { METHOD, FIELD, ANNOTATION_TYPE })
  2. @Retention(RUNTIME)
  3. @Constraint(validatedBy = FixLengthImpl.class)
  4. public @interface FixLength {
  5. int length();
  6. String message() default "{net.zhepu.web.valid.fixlength.message}";
  7. Class<?>[] groups() default {};
  8. Class<? extends Payload>[] payload() default {};
  9. }

及具体的验证实现类如下

  1. public class FixLengthImpl implements ConstraintValidator<FixLength, String> {
  2. private int length;
  3. @Override
  4. public boolean isValid(String validStr,
  5. ConstraintValidatorContext constraintContext) {
  6. if (validStr.length() != length) {
  7. return false;
  8. } else {
  9. return true;
  10. }
  11. }
  12. @Override
  13. public void initialize(FixLength fixLen) {
  14. this.length = fixLen.length();
  15. }
  16. }

为使自定义验证标注的message正常显示,需要修改servlet context配置文件,新增messageSource bean,如下

  1. <bean id="messageSource"
  2. class="org.springframework.context.support.ReloadableResourceBundleMessageSource"
  3. p:fallbackToSystemLocale="true" p:useCodeAsDefaultMessage="false"
  4. p:defaultEncoding="UTF-8">
  5. <description>Base message source to handle internationalization
  6. </description>
  7. <property name="basenames">
  8. <list>
  9. <!-- main resources -->
  10. <value>classpath:valid/validation</value>
  11. </list>
  12. </property>
  13. </bean>

表示spring 将从路径valid/validation.properties中查找对于的message。 
新增valid bean 引用新增的messageSource bean,表示valid message将从messageSource bean 注入。

  1. <bean id="validator"
  2. class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"
  3. p:validationMessageSource-ref="messageSource">
  4. <description>Enable the bean validation provider, and configure it to
  5. use the messageSource when resolving properties</description>
  6. </bean>

修改 <mvc:annotation-driven> 增加对validator bean的引用

  1. <mvc:annotation-driven validator="validator" />

最后修改之前新增的pojo bean ,新增一个mobileNO属性并增加对自定义标注的引用

  1. @FixLength(length=11)
  2. private String mobileNO;

在前端jsp中也增加新字段的支持

  1. <tr>
  2. <td>mobileno</td>
  3. <td><form:input path="mobileNO" />
  4. </td>
  5. <td><form:errors path="mobileNO" cssClass="error" />
  6. </td>
  7. </tr>

可访问url http://localhost:8080/springmvc/valid?userName=winzip&email=winzip&mobileNO=138188888 
来查看修改的结果。

三 json输入的验证 
Spring mvc 3.0.5中对于json格式的输入直接使用@valid标注有问题,目前这个bug还未修复 (见 SPR-6709),预计在3.1 m2版本中会修复。 
在此之前,可以通过如下几种方式来对json(或xml)格式的输入来进行验证。 
1:在handler method中直接对输入结果进行验证

  1. @RequestMapping("/validJson1")
  2. @ResponseBody
  3. public JsonResult processSubmitjson(@RequestBody ValidModel vm,
  4. HttpServletRequest request) {
  5. JsonResult jsonRst = new JsonResult();
  6. Set<ConstraintViolation<ValidModel>> set = validator.validate(vm);
  7. for (ConstraintViolation<ValidModel> violation : set) {
  8. String propertyPath = violation.getPropertyPath().toString();
  9. ;
  10. String message = violation.getMessage();
  11. log.error("invalid value for: '" + propertyPath + "': "
  12. + message);
  13. }
  14. if (!set.isEmpty()){
  15. jsonRst.setSuccess(false);
  16. jsonRst.setMsg("输入有误!");
  17. return jsonRst;
  18. }
  19. jsonRst.setSuccess(true);
  20. jsonRst.setMsg("输入成功!");
  21. return jsonRst;
  22. }

可通过修改后的helloworld.jsp中的json valid test1按钮进行调用测试。

2:将此验证逻辑封装为一个AOP,当需验证的对象前有@valid标注和@RequestBody标注时开始验证 
新增handler method如下

  1. @RequestMapping("/validJson2")
  2. @ResponseBody
  3. public JsonResult testJson4(@RequestBody @Valid ValidModel vm){
  4. log.info("handle json for valid");
  5. return new JsonResult(true,"return ok");
  6. }

这里没有对输入值做任何验证,所有的验证都在AOP中完成。 
修改pom.xml增加对AOP相关类库的引用。

  1. <dependency>
  2. <groupId>org.aspectj</groupId>
  3. <artifactId>aspectjweaver</artifactId>
  4. <version>1.6.11</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>cglib</groupId>
  8. <artifactId>cglib</artifactId>
  9. <version>2.2.2</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.springframework</groupId>
  13. <artifactId>spring-aop</artifactId>
  14. <version>${org.springframework.version}</version>
  15. </dependency>

修改servet context xml,增加对aop的支持。

  1. <!-- enable Spring AOP support -->
  2. <aop:aspectj-autoproxy proxy-target-class="true" />

最后,新增AOP类

  1. public class CustomerValidatorAOP {
  2. private Validator validator;
  3. @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
  4. private void controllerInvocation() {
  5. }
  6. @Around("controllerInvocation()")
  7. public Object aroundController(ProceedingJoinPoint joinPoint) throws Throwable {
  8. MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
  9. Method method = methodSignature.getMethod();
  10. Annotation[] annotationList = method.getAnnotations();
  11. /* for(Annotation anno:annotationList){
  12. System.out.println(ResponseBody.class.isInstance(anno));
  13. }
  14. */
  15. Annotation[][] argAnnotations = method.getParameterAnnotations();
  16. String[] argNames = methodSignature.getParameterNames();
  17. Object[] args = joinPoint.getArgs();
  18. for (int i = 0; i < args.length; i++) {
  19. if (hasRequestBodyAndValidAnnotations(argAnnotations[i])) {
  20. Object ret = validateArg(args[i], argNames[i]);
  21. if(ret != null){
  22. return ret;
  23. }
  24. }
  25. }
  26. return joinPoint.proceed(args);
  27. }
  28. private boolean hasRequestBodyAndValidAnnotations(Annotation[] annotations) {
  29. if (annotations.length < 2)
  30. return false;
  31. boolean hasValid = false;
  32. boolean hasRequestBody = false;
  33. for (Annotation annotation : annotations) {
  34. if (Valid.class.isInstance(annotation))
  35. hasValid = true;
  36. else if (RequestBody.class.isInstance(annotation))
  37. hasRequestBody = true;
  38. if (hasValid && hasRequestBody)
  39. return true;
  40. }
  41. return false;
  42. }
  43. private JsonResult validateArg(Object arg, String argName) {
  44. BindingResult result = getBindingResult(arg, argName);
  45. validator.validate(arg, result);
  46. if (result.hasErrors()) {
  47. JsonResult jsonresult = new JsonResult();
  48. jsonresult.setSuccess(false);
  49. jsonresult.setMsg("fail");
  50. return jsonresult;
  51. }
  52. return null;
  53. }
  54. private BindingResult getBindingResult(Object target, String targetName) {
  55. return new BeanPropertyBindingResult(target, targetName);
  56. }
  57. @Required
  58. public void setValidator(Validator validator) {
  59. this.validator = validator;
  60. }

这里只考虑了输入为json格式的情况,仅仅作为一种思路供参考,实际使用时需要根据项目具体情况进行调整。 
可通过修改后的helloworld.jsp中的json valid test2按钮进行调用测试。

原文:http://starscream.iteye.com/blog/1068905

SpringMVC 使用JSR-303进行校验 @Valid的更多相关文章

  1. SpringMVC中的 JSR 303 数据校验框架说明

    JSR 303 是java为Bean数据合法性校验提供的标准框架,它已经包含在JavaEE 6.0中. JSR 303 通过在Bean属性上标注类似于@NotNull.@Max等标准的注解指定校验规则 ...

  2. JSR 303 进行后台数据校验

    一.JSR 303 1.什么是 JSR 303? JSR 是 Java Specification Requests 的缩写,即 Java 规范提案. 存在各种各样的 JSR,简单的理解为 JSR 是 ...

  3. SpringMVC中实现Bean Validation(JSR 303 JSR 349 JSR 380)

    JSR 303是针对bean数据校验提出的一个规范.使用注解方式实现数据校验. 每个注解的用法这里就不多介绍,请移步JSR 303 - Bean Validation 介绍及最佳实践 笔者上面提到的J ...

  4. Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验,使用消息资源文件对消息国际化

    导包和配置 导入 JSR 303 的包.hibernate valid 的包 <dependency> <groupId>org.hibernate.validator< ...

  5. SpringMVC 数据转换 & 数据格式化 & 数据校验

    数据绑定流程 1. Spring MVC 主框架将 ServletRequest 对象及目标方法的入参实例传递给 WebDataBinderFactory 实例,以创建 DataBinder 实例对象 ...

  6. SpringMVC——数据转换 & 数据格式化 & 数据校验

    一.数据绑定流程 1. Spring MVC 主框架将 ServletRequest 对象及目标方 法的入参实例传递给 WebDataBinderFactory 实例,以创 建 DataBinder ...

  7. JSR 303 - Bean Validation 介绍及最佳实践

    JSR 303 - Bean Validation 介绍及最佳实践 JSR 303 – Bean Validation 是一个数据验证的规范,2009 年 11 月确定最终方案.2009 年 12 月 ...

  8. JSR教程1——JSR 303 - Bean Validation介绍

    1.Bean Validation 在任何时候,当你要处理一个应用程序的业务逻辑,数据校验是你必须要考虑和面对的事情.应用程序必须通过某种手段来确保输入进来的数据从语义上来讲是正确的.在通常的情况下, ...

  9. JSR 303 - Bean Validation 介绍及最佳实践(转)

    JSR 303 – Bean Validation 是一个数据验证的规范,2009 年 11 月确定最终方案.2009 年 12 月 Java EE 6 发布,Bean Validation 作为一个 ...

随机推荐

  1. Java并发编程笔记之CyclicBarrier源码分析

    JUC 中 回环屏障 CyclicBarrier 的使用与分析,它也可以实现像 CountDownLatch 一样让一组线程全部到达一个状态后再全部同时执行,但是 CyclicBarrier 可以被复 ...

  2. java基础之继承(一)

    虽然说java中的面向对象的概念不多,但是具体的细节还是值得大家学习研究,java中的继承实际上就是子类拥有父类所有的内容(除私有信息外),并对其进行扩展.下面是我的笔记,主要包含以下一些内容点: 构 ...

  3. 【Elasticsearch全文搜索引擎实战】之Head插件实践

    简介 Elasticsearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearch是用Java开发的,并作为Ap ...

  4. ext js 4.0 grid表格根据列值的不同给行设置不同的背景颜色

    Code: Ext.create('Ext.grid.Panel', { ... viewConfig: { getRowClass: function(record) { return record ...

  5. LeetCode子域名访问计数-Python3.7<五>

    上一篇:LeetCode 键盘行<四> 题目:https://leetcode-cn.com/problems/subdomain-visit-count/description/ 一个网 ...

  6. activeX

    对外接口和classid在idl文件中,接口功能实现在ctrl类中实现

  7. 数据结构(java版)学习笔记(四)——线性表之循环链表

    单向循环链表 PS:有阴影的结点是头结点 概念: 最后一个结点的链域值不为NULL,而是指向头结点 特点: 从表中的任意结点出发,都可以找到表中其他结点 循环条件 p==h 双向链表 概念 链表中的每 ...

  8. 140 - The 12th Zhejiang Provincial Collegiate Programming Contest(第三部分)

    Earthstone Keeper Time Limit: 4 Seconds      Memory Limit: 65536 KB Earthstone Keeper is a famous ro ...

  9. css兼容问题(一)

    开头语:不用就忘,还是自己乖乖的记笔记吧! 正文开始:    (一)如果你的页面对IE7兼容没有问题,又不想大量修改现有代码,同时又能在IE8中正常使用,微软声称,开发商仅需要在目前兼容IE7的网站上 ...

  10. blfs(systemv版本)学习笔记-编译安装配置dhcpcd

    我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! dhcpcd项目地址:http://www.linuxfromscratch.org/blfs/view/8.3/basicne ...