springmvc使用JSR-303进行校验

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

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

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<spring.version>4.1.1.RELEASE</spring.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-core</artifactId>
			<version>2.4.0</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.4.0</version>
		</dependency>
		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.3.1</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.1.0</version>
		</dependency>
		<dependency>
			<groupId>javax.validation</groupId>
			<artifactId>validation-api</artifactId>
			<version>1.1.0.Final</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>5.1.3.Final</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.7</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.11</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.8.4</version>
		</dependency>
		<dependency>
			<groupId>javax.el</groupId>
			<artifactId>javax.el-api</artifactId>
			<version>3.0.0</version>
		</dependency>
	</dependencies>

2.springmvc配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-3.0.xsd
		http://www.springframework.org/schema/mvc
		http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop.xsd">

	<!-- 默认的注解映射的支持 -->
	<mvc:annotation-driven/>
	<context:annotation-config/>
	<aop:aspectj-autoproxy/>

	<!-- 自动扫描的包名 -->
	<context:component-scan base-package="spring.test.web.controller"/>

	<bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />

</beans>

3.写java代码了

先建一个User类

public class User {
	@NotNull
	private String username;

	@NotNull(message = "密码不能为空")
	private String password;

	public String getUsername() {
		return username;
	}

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

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

}

然后建一个controller试试

@ResponseBody
@RequestMapping("/test1")
public AjaxResponse validateTest1(@Valid User user, BindingResult result){
	AjaxResponse ajaxResponse = new AjaxResponse();
	Map<String, Object> map = new HashMap<>();
	if(result.hasErrors()){
		ajaxResponse.setSuccess(false);
		ajaxResponse.setHasErrors(true);
		map.put("errors", result.getAllErrors());
	}
	else {
		map.put("now", new Date());
		map.put("user", user);
	}
	ajaxResponse.setData(map);
	return ajaxResponse;
}

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

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

然后写个测试方法试试

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

第一个请求的结果是

{"success":false,"message":null,"hasErrors":true,"data":[{"name":"user","message":"may not be null"},{"name":"user","message":"密码不能为空"}]}

第二个请求结果是

{"success":true,"message":null,"hasErrors":false,"data":{"now":1420788232169,"user":{"username":"testusername","password":"testpassword"}}}

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

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

@Aspect
public class ValidAspect {

	@Autowired private Validator validator;

	@Around("@annotation(org.springframework.web.bind.annotation.ResponseBody)")
	public Object doTest(ProceedingJoinPoint pjp) throws Throwable{
		MethodSignature signature = (MethodSignature) pjp.getSignature();
		Method method = signature.getMethod();
		if(!AjaxResponse.class.equals(method.getReturnType())){
			pjp.proceed();
		}
		Object[] args = pjp.getArgs();
		Annotation[][] annotations = method.getParameterAnnotations();
		for(int i = 0; i < annotations.length; i++){
			if(!hasValidAnnotation(annotations[i])){
				continue;
			}
			if(!(i < annotations.length-1 && args[i+1] instanceof BindingResult)){
				//验证对象后面没有跟bindingResult,事实上如果没有应该到不了这一步
				continue;
			}
			BindingResult result = (BindingResult) args[i+1];
			if(result.hasErrors()){
				AjaxResponse ajaxResponse = new AjaxResponse();
				ajaxResponse.setSuccess(false);
				ajaxResponse.setHasErrors(true);
				ajaxResponse.setData(processErrors(result));
				return ajaxResponse;
			}
		}
		return pjp.proceed();
	}

	private boolean hasValidAnnotation(Annotation[] annotations){
		if(annotations == null){
			return false;
		}
		for(Annotation annotation : annotations){
			if(annotation instanceof Valid){
				return true;
			}
		}
		return false;
	}

	private List<BindingError> processErrors(BindingResult result){
		if(result != null && result.hasErrors()){
			List<BindingError> list = new ArrayList<BindingError>();
			for(ObjectError error : result.getAllErrors()){
				BindingError be = new BindingError();
				be.setMessage(error.getDefaultMessage());
				be.setName(error.getObjectName());
				list.add(be);
			}
			return list;
		}
		return null;
	}
}

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

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

@ResponseBody
@RequestMapping("/test2")
public AjaxResponse validateTest2(@Valid User user, BindingResult result){
	AjaxResponse ajaxResponse = new AjaxResponse();
	Map<String, Object> map = new HashMap<>();
	map.put("now", new Date());
	map.put("user", user);
	ajaxResponse.setData(map);
	return ajaxResponse;
}

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

写测试方式试一下

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

第一个请求结果是

{"success":false,"message":null,"hasErrors":true,"data":[{"name":"user","message":"密码不能为空"},{"name":"user","message":"may not be null"}]}

第二个请求结果是

{"success":true,"message":null,"hasErrors":false,"data":{"now":1420788479105,"user":{"username":"testusername","password":"testpassword"}}}

效果跟上面是一样的

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

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

时间: 2024-11-02 16:42:29

springmvc使用JSR-303进行校验的相关文章

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

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

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

JSR 303是针对bean数据校验提出的一个规范.使用注解方式实现数据校验. 每个注解的用法这里就不多介绍,请移步JSR 303 - Bean Validation 介绍及最佳实践 笔者上面提到的JSR303是专家组成员向JCP提交的第一版Bean Validation, 主流Bean Validation使用Hibernate的实现,本文使用hibernate-validator 各个版本的规范对应关系如下: JSR 380 (Bean Validation 2.0) JSR 349 (Be

SpringMVC 数据转换 &amp; 数据格式化 &amp; 数据校验

数据绑定流程 1. Spring MVC 主框架将 ServletRequest 对象及目标方法的入参实例传递给 WebDataBinderFactory 实例,以创建 DataBinder 实例对象2. DataBinder 调用装配在 Spring MVC 上下文中的 ConversionService 组件进行数据类型转换.数据格式化工作.将 Servlet 中的请求信息填充到入参对象中3. 调用 Validator 组件对已经绑定了请求消息的入参对象进行数据合法性校验,并最终生成数据绑定

SpringMVC——数据转换 &amp; 数据格式化 &amp; 数据校验

一.数据绑定流程 1. Spring MVC 主框架将 ServletRequest 对象及目标方 法的入参实例传递给 WebDataBinderFactory 实例,以创 建 DataBinder 实例对象 2. DataBinder 调用装配在 Spring MVC 上下文中的 ConversionService 组件进行数据类型转换.数据格式 化工作.将 Servlet 中的请求信息填充到入参对象中 3. 调用 Validator 组件对已经绑定了请求消息的入参对象 进行数据合法性校验,并

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

JSR 303 – Bean Validation 是一个数据验证的规范,2009 年 11 月确定最终方案.2009 年 12 月 Java EE 6 发布,Bean Validation 作为一个重要特性被包含其中.本文将对 Bean Validation 的主要功能进行介绍,并通过一些示例来演示如何在 Java 开发过程正确的使用 Bean Validation. 1 评论: 安 大鹏, 软件工程师, IBM 杨 乐, 软件工程师, IBM 翁 志弘, 软件工程师, IBM 2011 年

JSR 303 - Bean Validation 是什么?

关于 Bean Validation JSR 303 - Bean Validation 是jree6 中的一项子规范,JSR 303 - Bean Validation着重解决以下实际问题: 在任何时候,当你要处理一个应用程序的业务逻辑,数据校验是你必 须要考虑和面对的事情.应用程序必须通过某种手段来确保输入进来的数据从语义上来讲是正确的.在通常的情况下,应用程序是分层的,不同的层由不同的开发人 员来完成.很多时候同样的数据验证逻辑会出现在不同的层,这样就会导致代码冗余和一些管理的问题,比如说

JSR 303标准

JSR 303是Java为bean数据合法性校验提供的标准框架,JSR 303通过在Bean属性上标注类似于@NotNull.@Max等标准的注解指定校验规则,并通过标准的校验接口对bean进行验证.可用注解的列表如下:

JSR 303 - Bean Validation 简介及使用方法

一.JSR-303简介 JSR-303 是 JAVA EE 6 中的一项子规范,叫做 Bean Validation,官方参考实现是Hibernate Validator. 此实现与 Hibernate ORM 没有任何关系. JSR 303 用于对 Java Bean 中的字段的值进行验证. Spring MVC 3.x 之中也大力支持 JSR-303,可以在控制器中对表单提交的数据方便地验证. 注:可以使用注解的方式进行验证 二.准备校验时使用的JAR validation-api-1.0.

使用JSR 303和AOP简化你的接口开发

本文出处:http://blog.csdn.net/chaijunkun/article/details/44854071,转载请注明.由于本人不定期会整理相关博文,会对相应内容作出完善.因此强烈建议在原始出处查看此文. 前言 如今互联网项目都采用HTTP接口形式进行开发.无论是Web调用还是智能设备APP调用,只要约定好参数形式和规则就能够协同开发.返回值用得最多的就是JSON形式.服务端除了保证正常的业务功能,还要经常对传进来的参数进行验证,例如某些参数不能为空,字符串必须含有可见字符,数值

SpringMVC中使用Jcaptcha实现校验码验证

SpringMVC中使用Jcaptcha实现校验码验证:http://www.tuicool.com/articles/rMzAFj 本文将使用Jcaptcha实现校验码验证,并演示在Spring/SpringMVC环境下的使用方法. 1. maven依赖 注:请按需对需要排除的依赖进行增减 <dependency> <groupId>com.octo.captcha</groupId> <artifactId>jcaptcha-all</artifa