须要检查的java bean html
Entity.javajava
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; } }
值校验的测试类git
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()); } } }
输出结果web
这里有一个国际化的key值,国际化文件在org.hibernate.validator下面的一系列的properites文件里面,若是须要自定义那么能够拷贝出来放在src目录下正则表达式
这里咱们拷贝一个出来,新增一个key为maxlength=字符串长度最大不能超过{max} ,可使用动态参数,这里的max值就是注解里面设定的值spring
而后修改Entity.java,name属性的message="{maxlength}"api
@Length(max=1,message="{maxlength}") //{maxlength}对应配置文件中的key. 必须有{} private String name;
再次运行结果以下mvc
首先自定义一个注解CannotContainSpaces (不能包含空格)app
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.javajsp
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的时候
首先新增配置文件内容(实体类里面的注解与上面彻底相同)
<!-- 国际化配置 --> <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());