springmvc使用JSR-303进行校验

源自:http://blog.csdn.net/tsingheng/article/details/42555307

下面提供一种springmvc的校验方案,一般没有校验或者手动写validator的话都要写好多代码好多if判断,使用JSR-303规范校验只需要在Pojo字段上加上相应的注解就可以实现校验了

1.依赖的jar包,我直接贴pom了

  1. <properties>  
  2.     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  3.     <spring.version>4.1.1.RELEASE</spring.version>  
  4. </properties>  
  5.   
  6. <dependencies>  
  7.     <dependency>  
  8.         <groupId>com.fasterxml.jackson.core</groupId>  
  9.         <artifactId>jackson-core</artifactId>  
  10.         <version>2.4.0</version>  
  11.     </dependency>  
  12.     <dependency>  
  13.         <groupId>com.fasterxml.jackson.core</groupId>  
  14.         <artifactId>jackson-databind</artifactId>  
  15.         <version>2.4.0</version>  
  16.     </dependency>  
  17.     <dependency>  
  18.         <groupId>commons-fileupload</groupId>  
  19.         <artifactId>commons-fileupload</artifactId>  
  20.         <version>1.3.1</version>  
  21.     </dependency>  
  22.     <dependency>  
  23.         <groupId>javax.servlet</groupId>  
  24.         <artifactId>javax.servlet-api</artifactId>  
  25.         <version>3.1.0</version>  
  26.     </dependency>  
  27.     <dependency>  
  28.         <groupId>javax.validation</groupId>  
  29.         <artifactId>validation-api</artifactId>  
  30.         <version>1.1.0.Final</version>  
  31.     </dependency>  
  32.     <dependency>  
  33.         <groupId>org.hibernate</groupId>  
  34.         <artifactId>hibernate-validator</artifactId>  
  35.         <version>5.1.3.Final</version>  
  36.     </dependency>  
  37.     <dependency>  
  38.         <groupId>org.springframework</groupId>  
  39.         <artifactId>spring-orm</artifactId>  
  40.         <version>${spring.version}</version>  
  41.     </dependency>  
  42.     <dependency>  
  43.         <groupId>org.springframework</groupId>  
  44.         <artifactId>spring-context</artifactId>  
  45.         <version>${spring.version}</version>  
  46.     </dependency>  
  47.     <dependency>  
  48.         <groupId>org.springframework</groupId>  
  49.         <artifactId>spring-web</artifactId>  
  50.         <version>${spring.version}</version>  
  51.     </dependency>  
  52.     <dependency>  
  53.         <groupId>org.springframework</groupId>  
  54.         <artifactId>spring-webmvc</artifactId>  
  55.         <version>${spring.version}</version>  
  56.     </dependency>  
  57.     <dependency>  
  58.         <groupId>org.springframework</groupId>  
  59.         <artifactId>spring-test</artifactId>  
  60.         <version>${spring.version}</version>  
  61.     </dependency>  
  62.     <dependency>  
  63.         <groupId>org.slf4j</groupId>  
  64.         <artifactId>slf4j-log4j12</artifactId>  
  65.         <version>1.7.7</version>  
  66.     </dependency>  
  67.     <dependency>  
  68.         <groupId>junit</groupId>  
  69.         <artifactId>junit</artifactId>  
  70.         <version>4.11</version>  
  71.         <scope>test</scope>  
  72.     </dependency>  
  73.     <dependency>  
  74.         <groupId>org.aspectj</groupId>  
  75.         <artifactId>aspectjweaver</artifactId>  
  76.         <version>1.8.4</version>  
  77.     </dependency>  
  78.     <dependency>  
  79.         <groupId>javax.el</groupId>  
  80.         <artifactId>javax.el-api</artifactId>  
  81.         <version>3.0.0</version>  
  82.     </dependency>  
  83. </dependencies>  
2.springmvc配置
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"  
  4.     xmlns:context="http://www.springframework.org/schema/context"  
  5.     xmlns:mvc="http://www.springframework.org/schema/mvc"  
  6.     xmlns:aop="http://www.springframework.org/schema/aop"  
  7.     xsi:schemaLocation="http://www.springframework.org/schema/beans   
  8.         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
  9.         http://www.springframework.org/schema/tx   
  10.         http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
  11.         http://www.springframework.org/schema/context  
  12.         http://www.springframework.org/schema/context/spring-context-3.0.xsd  
  13.         http://www.springframework.org/schema/mvc  
  14.         http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd  
  15.         http://www.springframework.org/schema/aop   
  16.         http://www.springframework.org/schema/aop/spring-aop.xsd">  
  17.   
  18.     <!-- 默认的注解映射的支持 -->  
  19.     <mvc:annotation-driven/>  
  20.     <context:annotation-config/>  
  21.     <aop:aspectj-autoproxy/>  
  22.   
  23.     <!-- 自动扫描的包名 -->  
  24.     <context:component-scan base-package="spring.test.web.controller"/>  
  25.       
  26.     <bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />  
  27.       
  28. </beans>  

3.写java代码了

先建一个User类

  1. public class User {  
  2.     @NotNull  
  3.     private String username;  
  4.       
  5.     @NotNull(message = "密码不能为空")  
  6.     private String password;  
  7.       
  8.     public String getUsername() {  
  9.         return username;  
  10.     }  
  11.       
  12.     public void setUsername(String username) {  
  13.         this.username = username;  
  14.     }  
  15.       
  16.     public String getPassword() {  
  17.         return password;  
  18.     }  
  19.       
  20.     public void setPassword(String password) {  
  21.         this.password = password;  
  22.     }  
  23.       
  24. }  
然后建一个controller试试
  1. @ResponseBody  
  2. @RequestMapping("/test1")  
  3. public AjaxResponse validateTest1(@Valid User user, BindingResult result){  
  4.     AjaxResponse ajaxResponse = new AjaxResponse();  
  5.     Map<String, Object> map = new HashMap<>();  
  6.     if(result.hasErrors()){  
  7.         ajaxResponse.setSuccess(false);  
  8.         ajaxResponse.setHasErrors(true);  
  9.         map.put("errors", result.getAllErrors());  
  10.     }  
  11.     else {  
  12.         map.put("now"new Date());  
  13.         map.put("user", user);  
  14.     }  
  15.     ajaxResponse.setData(map);  
  16.     return ajaxResponse;  
  17. }  

这个方法第一个参数上加了@Valid标注,第二个参数是必须的而且必须紧跟着@Valid参数之后,校验结果都在这个result里面

方法逻辑比较简单,调用result.hasErrors()看校验有没有错误,有错误的话就把所有的错误放进结果返回给客户端,如果没有错误就返回当前时间跟user对象

然后写个测试方法试试

  1. @Test  
  2. public void test1() throws Exception{  
  3.     this.mockMvc.perform(post("/validator/test1")).andDo(print());  
  4.     this.mockMvc.perform(post("/validator/test1").param("username""testusername").param("password""testpassword")).andDo(print());  
  5. }  

第一个请求的结果是
[javascript] view plaincopy在CODE上查看代码片派生到我的代码片
  1. {"success":false,"message":null,"hasErrors":true,"data":[{"name":"user","message":"may not be null"},{"name":"user","message":"密码不能为空"}]}  

第二个请求结果是
[javascript] view plaincopy在CODE上查看代码片派生到我的代码片
  1. {"success":true,"message":null,"hasErrors":false,"data":{"now":1420788232169,"user":{"username":"testusername","password":"testpassword"}}}  

很明显第一次请求没有用户名和密码两个字段校验都没有通过,第二次是成功的

用起来还是很简单的,但是如果我不想每次都在controller方法里写if(result.hasErrors())怎么办呢,写个切面,把if写在切面里,如果有errors直接就返回了,不用再执行controller方法了

  1. @Aspect  
  2. public class ValidAspect {  
  3.       
  4.     @Autowired private Validator validator;  
  5.       
  6.     @Around("@annotation(org.springframework.web.bind.annotation.ResponseBody)")  
  7.     public Object doTest(ProceedingJoinPoint pjp) throws Throwable{  
  8.         MethodSignature signature = (MethodSignature) pjp.getSignature();  
  9.         Method method = signature.getMethod();  
  10.         if(!AjaxResponse.class.equals(method.getReturnType())){  
  11.             pjp.proceed();  
  12.         }  
  13.         Object[] args = pjp.getArgs();  
  14.         Annotation[][] annotations = method.getParameterAnnotations();  
  15.         for(int i = 0; i < annotations.length; i++){  
  16.             if(!hasValidAnnotation(annotations[i])){  
  17.                 continue;  
  18.             }  
  19.             if(!(i < annotations.length-1 && args[i+1instanceof BindingResult)){  
  20.                 //验证对象后面没有跟bindingResult,事实上如果没有应该到不了这一步  
  21.                 continue;  
  22.             }  
  23.             BindingResult result = (BindingResult) args[i+1];  
  24.             if(result.hasErrors()){  
  25.                 AjaxResponse ajaxResponse = new AjaxResponse();  
  26.                 ajaxResponse.setSuccess(false);  
  27.                 ajaxResponse.setHasErrors(true);  
  28.                 ajaxResponse.setData(processErrors(result));  
  29.                 return ajaxResponse;  
  30.             }  
  31.         }  
  32.         return pjp.proceed();  
  33.     }  
  34.   
  35.     private boolean hasValidAnnotation(Annotation[] annotations){  
  36.         if(annotations == null){  
  37.             return false;  
  38.         }  
  39.         for(Annotation annotation : annotations){  
  40.             if(annotation instanceof Valid){  
  41.                 return true;  
  42.             }  
  43.         }  
  44.         return false;  
  45.     }  
  46.       
  47.     private List<BindingError> processErrors(BindingResult result){  
  48.         if(result != null && result.hasErrors()){  
  49.             List<BindingError> list = new ArrayList<BindingError>();  
  50.             for(ObjectError error : result.getAllErrors()){  
  51.                 BindingError be = new BindingError();  
  52.                 be.setMessage(error.getDefaultMessage());  
  53.                 be.setName(error.getObjectName());  
  54.                 list.add(be);  
  55.             }  
  56.             return list;  
  57.         }  
  58.         return null;  
  59.     }  
  60. }  

注意要在springmvc配置文件加一行<bean class="spring.test.web.aop.ValidAspect"/>

然后再写个方法逻辑跟上面的类似

  1. @ResponseBody  
  2. @RequestMapping("/test2")  
  3. public AjaxResponse validateTest2(@Valid User user, BindingResult result){  
  4.     AjaxResponse ajaxResponse = new AjaxResponse();  
  5.     Map<String, Object> map = new HashMap<>();  
  6.     map.put("now"new Date());  
  7.     map.put("user", user);  
  8.     ajaxResponse.setData(map);  
  9.     return ajaxResponse;  
  10. }  

这里没有再去判断hasErrors()了,然后测试一下

写测试方式试一下

  1. @Test  
  2. public void test2() throws Exception{  
  3.     this.mockMvc.perform(post("/validator/test2")).andDo(print());  
  4.     this.mockMvc.perform(post("/validator/test2").param("username""testusername").param("password""testpassword")).andDo(print());  
  5. }  

第一个请求结果是
[javascript] view plaincopy在CODE上查看代码片派生到我的代码片
  1. {"success":false,"message":null,"hasErrors":true,"data":[{"name":"user","message":"密码不能为空"},{"name":"user","message":"may not be null"}]}  
第二个请求结果是
  1. {"success":true,"message":null,"hasErrors":false,"data":{"now":1420788479105,"user":{"username":"testusername","password":"testpassword"}}}  
效果跟上面是一样的

当然我这个切面仅仅是个示范,我拦截的是带有ResponseBody注解的方法,我这些方法会返回一个统一的格式,如果是要返回别的视图就要自己定义注解加其他参数了

JSR-303原生支持的校验注解也是有限的,如果要实现其他的验证,可以自己拓展,拓展方法就下次再说了,我也才刚接触。


发布了4 篇原创文章 · 获赞 19 · 访问量 39万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章