您的位置:首页 > 编程语言 > Java开发

【补充】Hibernate validator使用和自定义validator及整合Spring MVC

2016-12-27 00:00 274 查看

Hibernate validator使用

导入validation-api-xxx.jar 以及 hibernate-validator-xxx.Final.jar

需要检查的java bean

Entity.java

import javax.validation.constraints.Max;
import org.hibernate.validator.constraints.Length;
public class Entity {
@Max(value=3)//最大值为3
private int age;
@Length(max=1) //字符串长度最大为1,hibernate 扩展的
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

值校验的测试类

import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
public class Tv {
public static void main(String[] args) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();

Entity entity = new Entity();
entity.setAge(12);
entity.setName("admin");
Set<ConstraintViolation<Entity>> constraintViolations = validator.validate(entity);
for (ConstraintViolation<Entity> constraintViolation : constraintViolations) {
System.out.println("对象属性:"+constraintViolation.getPropertyPath());
System.out.println("国际化key:"+constraintViolation.getMessageTemplate());
System.out.println("错误信息:"+constraintViolation.getMessage());
}

}
}

输出结果



这里有一个国际化的key值,国际化文件在org.hibernate.validator下面的一系列的properites文件里面,如果需要自定义那么可以拷贝出来放在src目录下



这里我们拷贝一个出来,新增一个key为maxlength=字符串长度最大不能超过{max} ,可以使用动态参数,这里的max值就是注解里面设定的值

然后修改Entity.java,name属性的message="{maxlength}"

@Length(max=1,message="{maxlength}") //{maxlength}对应配置文件中的key. 必须有{}
private String name;

再次运行结果如下



自定义validator

首先自定义一个注解CannotContainSpaces (不能包含空格)

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;

@Constraint(validatedBy = CannotContainSpacesValidator.class) //具体的实现
@Target( { java.lang.annotation.ElementType.METHOD,
java.lang.annotation.ElementType.FIELD })
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Documented
public @interface CannotContainSpaces {
String message() default "{Cannot.contain.Spaces}"; //提示信息,可以写死,可以填写国际化的key

int length() default 5;

//下面这两个属性必须添加
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};

}

具体实现类CannotContainSpacesValidator.java

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class CannotContainSpacesValidator implements ConstraintValidator<CannotContainSpaces, String> {
private int len;
/**
* 初始参数,获取注解中length的值
*/
@Override
public void initialize(CannotContainSpaces arg0) {
this.len = arg0.length();
}

@Override
public boolean isValid(String str, ConstraintValidatorContext constraintValidatorContext) {
if(str != null){
if(str.indexOf(" ") < 0){
return true;
}
}else{
constraintValidatorContext.disableDefaultConstraintViolation();//禁用默认的message的值
//重新添加错误提示语句
constraintValidatorContext
.buildConstraintViolationWithTemplate("字符串不能为空").addConstraintViolation();
}
return false;
}

}

使用的时候直接注解到对象的属性上面就可以了

@CannotContainSpaces
private String name;

测试当name包含空格的时候 entity.setName("xx xx");



当name为null的时候



整合Spring MVC

首先新增配置文件内容(实体类里面的注解与上面完全相同)

<!-- 国际化配置 -->
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.CookieLocaleResolver" />
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>classpath:messages/messages</value>
<value>classpath:messages/Validation</value>
</list>
</property>
<property name="useCodeAsDefaultMessage" value="true" />
</bean>
<!-- 注册验证器 -->
<mvc:annotation-driven validator="validator" />

<!-- 注册验证器 补充方式二-->
<!--
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="webBindingInitializer">
<ref bean="webBindingInitializer" />
</property>
</bean>

<bean id="webBindingInitializer" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="validator" ref="validator" />
</bean>
-->

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
<!-- 这里配置将使用上面国际化配置的messageSource -->
<property name="validationMessageSource" ref="messageSource"/>
</bean>

在Spring MVC 控制器中方法属性如下

/**
* 这里的@Valid必须书写, bindingResult参数也必须书写在后面,否则验证不通过就会返回400
* @param entity
* @param result
* @return
*/
@RequestMapping(value="/valid")
public String validator(@Valid Entity entity,BindingResult result){
if(result.hasErrors()){
//如果严重没有通过,跳转提示
return "error";
}else{
//继续业务逻辑
}
return "success";
}

error.jsp中如下

导入spring标签库

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>

<!-- commandName 控制器参数中对象名称 -->
<form:form commandName="entity">
<!-- 显示全部错误信息用* -->
<form:errors path="*"/>
</form:form>
<hr/>
<!-- 对象名称.属性名称    如果该对象的指定属性没有通过校验那么显示错误信息(根据当前语言显示不同国家的文字) -->
<form:errors path="entity.name"/>

校验注解说明

Bean Validation 中内置的 constraint
@Null   被注释的元素必须为 null
@NotNull    被注释的元素必须不为 null
@AssertTrue     被注释的元素必须为 true
@AssertFalse    被注释的元素必须为 false
@Min(value)     被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)     被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)  被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value)  被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max=, min=)   被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction)     被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past   被注释的元素必须是一个过去的日期
@Future     被注释的元素必须是一个将来的日期
@Pattern(regex=,flag=)  被注释的元素必须符合指定的正则表达式
Hibernate Validator 附加的 constraint
@NotBlank(message =)   验证字符串非null,且长度必须大于0
@Email  被注释的元素必须是电子邮箱地址
@Length(min=,max=)  被注释的字符串的大小必须在指定的范围内
@NotEmpty   被注释的字符串的必须非空
@Range(min=,max=,message=)  被注释的元素必须在合适的范围内

注意
①:在整合Spring MVC的时候,ValidationMessages_zh_CN.properties文件如果不是放在src目录下(如上面放在src/messages/下面) 那么在属性文件里面不能使用动态参数获取了(如${length} ${max}这些). 必须将hibernate validation的国际化属性全部放到src目录下面才可以(不晓得为什么,如果你能解决顺便留个言)

②:我这里使用的是spring 4.1 + hibernate validation 5.1 ,如果你使用的是spring 3.2 需要对于的hibernate validation版本是 4.x的 不然在配置

org.springframework.validation.beanvalidation.LocalValidatorFactoryBean

这个的是会报错,

【补充】

当SpringMVC将接收到的参数映射成modelAttribute时,可能会出现异常,比如参数是字符型,接收对象的属性是数值型,则转换异常。此时SpringMVC也会把异常信息放到BindingResult中。但是异常信息没有经过国际化处理,如果要转换为国际化的信息,则要自己处理,方式如下:

通过BindingResult获取到FieldError对象error,在通过messageSource.getMessage()方法获取到国际化后的异常信息

@Autowired
private MessageSource messageSource;
...

FieldError error = bindingResult.getFieldError("fieldName");
String errorMessage = messageSource.getMessage(error, Locale.getDefault());
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息