springMVC中validation的使用

参考博客 :https://elf8848.iteye.com/blog/1299587

1 Spring MVC 校验器

从Spring3开始,Spring MVC能够自动校验被Controller层的输入对象。在之前的版本中都是程序员手动的完成这些逻辑。

1.1 java规范提案JSR-303 Bean 校验API概述

JSR-303规范中允许你对属性定义像这样的约束:

public class PersonForm {
	@NotNull(message="姓名不能为空")
    @Size(max=5,message="姓名最长五个字")
    private String name;

    @Min(message="年龄不能小于0",value=0)
    private int age;
}

当该类的示例被JSR-303校验时,这些约束将会生效。

1.2 配置Validation校验器的实现

Spring提供了JSR-303 Bean Validation API的全套支持。这包括支持将JSR303的实现bean化(组件化)。这将允许javax.validation.ValidatorFactory or javax.validation.Validator任何时刻都能够被注入。

<!-- 使用LocalValidatorFactoryBean 配置JSR-303校验器作为默认的校验器-->
<bean id="validator"
 class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>

JSR-303服务提供者,例如, Hibernate Validator需要被加入类路径或者能够被自动检测到,上面的配置能够自动触发JSR-303使用默认的引导机制进行初始化。

1.2.1 注入Validator

LocalValidatorFactoryBean 实现了 javax.validation.Validatorjavax.validation.Validatororg.springframework.validation.Validator接口
如果你的程序需要不同的校验器:你可以直接注入接口:

// 注入javax.validation.Validator
import javax.validation.Validator;

@Service
public class MyService {

    @Autowired
    private Validator validator;

// 注入 org.springframework.validation.Validator
import org.springframework.validation.Validator;
@Service
public class MyService {

    @Autowired
    private Validator validator;

1.3 配置自定义的约束

每个JSR-303校验约束包含两部分。

  • @Constraint 注解 声明约束(例,NotNull)和属性(例,message、value)
  • 实现了ConstraintValidator 约束接口的实现类

为了将声明与实现关联,每个@Constraint注释引用一个对应的ValidationConstraint实现类,在运行时,当在domain 模型中遇到约束注释时,ConstraintValidatorFactory实例化引用的实现。

默认情况下,LocalValidatorFactoryBean 会配置创建ConstraintValidator 的SpringConstraintValidatorFactory 工厂,因此自定义的约束校验器也能够注入到其它spring bean中去。

1.3.1 完整的代码示例

检测属性中是否包含敏感词汇。可以参考官方实现方法,例如@NotNull @Min

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

import com.pc.JSRValidator.constraint.MyConstraintValidator;

/**
 * @author zhouzixiang
 * 声明注解,并绑定注解和校验器的实现
 */
@Target({ METHOD, FIELD})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {MyConstraintValidator.class})
public @interface MyConstraint {
	
	String message() default "{不得包含敏感词汇}";
	
	String value(); //不得包含敏感词汇的值
	
	Class<?>[] groups() default { };

	Class<? extends Payload>[] payload() default {};
}

/**
 * @author zzx
 * 自定义约束实现ConstraintValidator接口不能包含 指定的敏感词汇
 * 该对象实例由Spring提供的工厂自动创建
 */
public class MyConstraintValidator implements ConstraintValidator<MyConstraint, String> {
	
	static Log log = LogFactory.getFactory().getInstance(MyConstraintValidator.class);
	
	private String aggressiveWord ; 
	
	public void initialize(MyConstraint constraintAnnotation) {
		this.aggressiveWord = constraintAnnotation.value();
		log.debug("包含敏感词汇:"+aggressiveWord);
	}

	public boolean isValid(String value, ConstraintValidatorContext context) {
		if (StringUtils.isNotBlank(value)) {
			System.out.println(value);
			if (value.contains(aggressiveWord)) {
				log.debug(value+"包含敏感词汇:"+aggressiveWord);
				return false;
			}
		}
		return true;
	}
}
	/**
	 *手动触发JSR校验器,没有用到@Valid注解
	 * 测试敏感词汇
	 */
	@Test
	public void testAggressive () {
		PersonForm personForm = new PersonForm();
		personForm.setAge(15);
		personForm.setName("诸葛正");
		personForm.setDescription("you are not SB!");
		Set<ConstraintViolation<PersonForm>> validResult = Validation.buildDefaultValidatorFactory().getValidator().validate(personForm);
		System.out.println(validResult);
	}

1.4 数据绑定配置

从Spring3 开始,校验器能够配置DataBinder 实例。调用binder.validate()能够触发校验,所有的错误自动填充到binderBindingResult中。
示例代码片段:

@Test
	public void test () {
		PersonForm personForm = new PersonForm();
		personForm.setAge(-1);
		//personForm.setAge(15);
		personForm.setName("诸葛正我正握");
//		System.out.println(personForm.getAge());
		DataBinder binder = new DataBinder(personForm);
		
		// the validator is the instance of org.springframework.validation.Validator 
		binder.setValidator(validator);

		// bind to the target object
//		binder.bind();

		// validate the target object
		binder.validate();

		// get BindingResult that includes any validation errors
		BindingResult results = binder.getBindingResult();
		List<ObjectError> allErrors = results.getAllErrors();
		for(ObjectError error : allErrors) {
			System.out.println(error.getDefaultMessage());
		}
	}

1.5 触发@Controller input 校验

为了触发Controller注解的校验功能,只需要使用**@Valid**: 在Validator校验器被正确配置后,Spring MVC会校验被**@Valid**标记的对象

@Controller
public class MyController {
    @RequestMapping("/foo", method=RequestMethod.POST)
    public void processFoo(@Valid Foo foo) { /* ... */ }

小记:@Valid注解是标准java规范(JSR-303)Bean验证Api的一部分,而不是Spring特有的

1.5.1 Spring MVC中使用Validatoe校验器

Validator 主要有两种配置方法:

  • 在@Controller的@InitBinder回调函数中调用binder.setValidator(Validator)
//好处为每个Controller配置不同的校验器
@Controller
public class MyController {

    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.setValidator(new FooValidator());
    }

    @RequestMapping("/foo", method=RequestMethod.POST)
    public void processFoo(@Valid Foo foo) { ... }

}

  • 在全局WebBindingInitializer上调用setValidator(Validator),配置方式
<!-- 所有的Controller使用相同的校验器-->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <mvc:annotation-driven validator="globalValidator"/>

</beans>

但有时你可能急需要全局的validator,有可能需要针对某个特殊的Controller应用不同的规则。因此,你可以使用上面的全局配置,然后在特定的controller中@InitBinder回调 进行特殊的配置。
@Controller
public class MyController {

    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.addValidators(new FooValidator());
    }

}

1.5.2 Spring MVC中使用JSR Validator校验

JSR-303下, javax.validation.Validator的单实例校验所有声明了约束的域模型。要使用Spring MVC配置JSR-303支持的验证器,只需向类路径添加一个JSR-303提供程序,例如Hibernate验证器。Spring MVC将检测到它,并自动跨所有控制器启用JSR-303支持。
配置如下:

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

    <!-- JSR-303 support will be detected on classpath and enabled automatically -->
    <mvc:annotation-driven/>

</beans>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值