因为从云笔记中粘贴过来的,代码格式就没有了。格式稍好点的地址:Spring验证
目标:
- Spring自带的验证方式
- 基于JSR303的验证
- 国际化显示错误信息
一:使用Spring自带的验证方式
该种方式相对来说麻烦一点,需要为每个需要验证的实体类编写一个验证类,不过好处是可以处理多字段组合验证以及业务逻辑等复杂验证
1.1:定义实体类(User)
public class User {
private String username;
private String nickname;
private String password;
//省略getter /setter
}
1.2:定义实体类验证类(UserValidator)
需要继承Validator接口
public class UserValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return User.class.equals(clazz);
}
public void validate(Object target, Errors errors) {
User user = (User)target;
if(StringUtils.isEmpty(user.getUsername())){
//1:使用这种方式,会报错(No message found under code 'empty.user.username.user.username' for locale 'zh_CN'.),因为rejectValue的第二个参数都是errorcode
//errors.rejectValue("username","empty.user.username");
//errors.rejectValue("username","用户名不能为空");
//2:正确用法:rejectValue(String filed,String errorcode,Object[] errorArgs,String defaultMessage)
errors.rejectValue("username","empty.user.username","用户名不能为空Default");
//使用该种方式,不需要配置ResourceBundleMessageSource
// ValidationUtils.rejectIfEmpty(errors,"username","empty.user.username","用户名不能为空");
} else {
int length = user.getUsername().length();
if(length<=3){
errors.rejectValue("username","min.length.user.username","用户名长度不能小于3Default");
}else if (length>=6){
errors.rejectValue("username","max.length.user.username","用户名不能大于6Default");
}
}
}
}
1.3:编写控制器代码:
@RequestMapping(value = "validatorBySpring", method = RequestMethod.GET)
public String validatorBySpringForm(@ModelAttribute("user") User user) {
return "validator/validatorBySpring";
}
/**
* 第一种,使用spring自带的validator
*/
@RequestMapping(value = "validatorBySpring", method = RequestMethod.POST)
public String validatorBySpring(@ModelAttribute("user") User user,
BindingResult result) {
userValidator.validate(user, result);
if (result.hasErrors()) {
return "validator/validatorBySpring";
}
return "validator/success";
}
注意:在get方法中,需要加上@ModelAttribute,否则无法访问,或者可以抽出来,写一个以下方法:
@ModelAttribute(“user")
public void getUser(){
return new User();
},这样的话,访问该控制器的时候都会调用该方法
1.4:前台
<form:form action="${ctx}/validator/validatorBySpring" method="post" modelAttribute="user">
<tr>
<td><form:label path="username" >Username</form:label></td>
<td><form:input path="username" ></form:input></td>
<td><form:errors path="username"></form:errors></td>
</tr>
<tr>
<td> <form:label path="password">password</form:label> </td>
<td> <form:input path="password"></form:input> </td>
<td><form:errors path="password"></form:errors> </td>
</tr>
<tr>
<td> <form:label path="email">email</form:label> </td>
<td> <form:input path="email"></form:input> </td>
<td><form:errors path="email"></form:errors> </td>
</tr>
<tr>
<td colspan="3">
<input type="submit" value="SUBMIT">
</td>
</tr>
</form:form>
1.5: 在上述代码已经可以完成Spring自带验证了,而且界面能正常显示错误信息,但是在实际过程中,错误信息采用的是硬编码,这是不可取的,所以,接下来需要国际化错误信息
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename">
<value>messages</value>
</property>
</bean>
messages_zh_CN.properties 在resources/下
empty.user.username=用户名不能为空
min.length.user.username=用户名长度不能小于3
max.length.user.username=用户名长度不能大于6
其中的errorcode可以随便写,只要在messages中对应上即可,在这种情况下,在实体验证类中,就可以使用第一种方式即:errors.rejectValue("username",”empty.user.username)。因为在message文件中有对应的errorcode,所以能正常显示
扩展:
1:不使用rejectValue,而是使用reject,界面该如何显示
eg:errors.reject(“empty.user.username”,”用户名不能为空");
直接在form中写如下:<form:errors />会显示全部错误
2:使用ValidationUtils
ValidationUtils.rejectIfEmpty(errors,"username","empty.user.username","用户名不能为空”);
Errors主要使用方法:
reject(String errorcode,Object[] errorArgs,String defaultMessage)
rejectValue(String filed,String errorcode,Object[] errorArgs,String defaultMessage)
BinderResult接口扩展了Erros接口,以便可以使用Spring的Validator对对象进行校验,同时获取绑定结果对象的信息。
二:使用基于jsr303的验证
在Spring3.x企业开发实战里面提到:通过binder.setValidator之后,Spring MVC将使用它对入参对象进行校验,将不再使用Spring框架装配的Validator对入参进行校验。换句话说:即使在入参上标注了@Valid注解,也不会再根据入参对象类中的jsr303注解进行校验了。
2.1:
1:使用jsr303注解,可以注解基于javax.validator或者基于hibernated 。之前觉得没有什么不同,但是今天发现还是有不同的
2.1.1使用之前的配置,不做任何修改,messages里面没有任何对应的errorcode
@NotEmpty
起作用了,提示:may not be empty ,为什么会显示这个会有解释
@NotEmpty(message = "{username.not.empty}")
提示:{username.not.empty}
|
不起作用的原因是:NotNull和NotEmpty是不同滴。
@NotNull
并没有进行验证,而是直接通过,也就是验证没有起作用
@NotNull(message = "{username.not.empty}”)
仍然没有起作用
2.1.2:在资源文件中配置如下:
username.not.empty=用户名不能为空1
@NotEmpty
显示 may not be empty
@NotEmpty(message = "{username.not.empty}")
提示:{username.not.empty} 。即,直接显示message里面的内容,而我要的是显示:用户名不能为空1
2.1.3:在资源文件配置如下:
username.not.empty=用户名不能为空1
NotNull.user.username=用户名不能为空
NotEmpty.user.username=用户名不能为空
@NotEmpty 提示:用户名不能为空
@NotEmpty(message = "{username.not.empty}”) 提示用户名不能为空,即:message里面的没有起作用,
去掉NotEmpty.user.username=用户名不能为空,则提示为{username.not.empty}
2.1.4:加上以上配置之后
<!-- 以下 validator ConversionService 在使用 mvc:annotation-driven 会 自动注册-->
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
<!-- 如果不加默认到 使用classpath下的 ValidationMessages.properties -->
<property name="validationMessageSource" ref="messageSource"/>
</bean>
资源文件还是如下:
username.not.empty=用户名不能为空1
NotNull.user.username=用户名不能为空
NotEmpty.user.username=用户名不能为空
注意,上面的并没有在mvc:annoation-driver中注册
@NotEmpty 提示用户名不能为空
@NotEmpty(message = "{username.not.empty}")提示用户名不能为空,即messages仍然没有起作用
去掉NotEmpty.user.username=用户名不能为空,则提示为{username.not.empty}
将<mvc:annotation-driven validator="validator" />
@NotEmpty 提示用户名不能为空
@NotEmpty(message = "{username.not.empty}")提示用户名不能为空,即messages仍然没有起作用
去掉NotEmpty.user.username=用户名不能为空,则提示为:用户名不能为空1
总结:因为不知道为什么基于javax.validator的注解不起作用,所以字总结基于hibernate的注解。这里一NotEmpty来举例。
首先,如果一旦在实体上标识了该注解,则就已经起作用了。如果不配置错误信息,将使用默认的:在hibernate-validator.jar中的Resource中,有一个ValidatorMessages.properties。里面有错误主力的默认显示:org.hibernate.validator.constraints.NotEmpty.message=may not be empty,这也就是为什么只配置了@NotEmpty之后显示 may not be empty的原因。当配置了自己的资源文件后,因为没有配置validator,所以还是显示之前的错误。那为什么后面没有配置validator。为什么NotEmpty.user.usrname能显示而{username.not.empty}不能正常显示呢?这是因为FileError实现了MessageResourceResolvable接口,里面有自己的一套规则:
Annotation.entity.attribute。所以,我使用NotEmpty.user.username能显示中文,而使用{usrname.not.empty}却显示{username.not.empty}。在配置了validator之后,因为<mvc:annotaitonDriver 中没有指定validator,所以相当于没有配置。即:2.1.3的测试结果和2.1.4的测试结果一样。只有配置了 mvc:annotaiton-driver validator=“validator”之后,才能自定义错误格式,这种情况下才@NotEmpty{message={username.not.empty}}才能显示出来,不过NotEmpty.user.username这样格式的优先级比较高,两者放在一起,还是会显示后者。这就是,为什么在所有的一切都配置好之后,还是会显示“用户名不能为空”,只有在messages里面去掉之后才能显示username.not.empty的信息。
问题:
1:基于spring自带的validator前台不使用Spring form标签如何展示错误?
2:使用ajax方式,怎样进行验证,和上面是同样的问题,也就是不使用表单
其中,基于jsr303的可以实现,可以参考springside里面的代码,但是自带的却不好实现,因为循环FiledError的时候,只能得到errorcode和defultMessage,得不到国际化信息
资料:
JSR 303 - Bean Validation 介绍及最佳实践
http://www.ibm.com/developerworks/cn/java/j-lo-jsr303/
开涛的博客:跟我学Spring mvc 3
http://jinnianshilongnian.iteye.com/blog/1617451
spring 3.x 企业开发实战
相关推荐
Spring 基于注释的校验机制: 1) 支持Spring框架定义的Validator接口定义的校验。 2) 支持JSR303 Bean Validation定义的校验规范。 3) 比较复杂的验证和自定义验证方法
1.15 小结 56 第2章 高级Spring IoC容器 57 2.1 调用静态工厂方法创建Bean 57 2.1.1 问题 57 2.1.2 解决方案 57 2.1.3 工作原理 57 2.2 调用一个实例工厂方法创建Bean 58 2.2.1 问题 58 2.2.2 ...
1.5 SpringMVC + spring3.1.1 + hibernate4.1.0 集成及常见问题总结 1.6 »Spring 之AOP AspectJ切入点语法详解(最全了,不需要再去其他地找了) 1.7 Spring开闭原则的表现-BeanPostProcessor扩展点-2 1.8 Spring...
1.15 小结 56 第2章 高级Spring IoC容器 57 2.1 调用静态工厂方法创建Bean 57 2.1.1 问题 57 2.1.2 解决方案 57 2.1.3 工作原理 57 2.2 调用一个实例工厂方法创建Bean 58 2.2.1 问题 58 2.2.2 ...
Spring.NET是一个应用程序框架,其目的是协助开发人员创建企业级的.NET应用程序。它提供了很多方面的功能,比如依赖注入、面向方面编程(AOP)、数据访问抽象及ASP.NET扩展等等。Spring.NET以Java版的Spring框架为...
Spring 3.0重要特性总结如下: ◆Spring表达式(SpEL):用于bean定义的核心表达式分析器 ◆对基于注释的组件的更多支持:允许通过元注释创建注释的“快捷方式” ◆标准化的依赖性注入注释:对Java中依赖性注入的...
Spring初探 准备工作 构建Spring基础代码 Spring 基础语义 Dependency Injection 依赖注入的几种实现类型 Type1 接口注入 Type2 设值注入 Type3 构造子注入 几种依赖注入模式的对比总结 Spring Bean封装...
3、了解Spring中两种动态代理方式的区别; 4、掌握基于XML和注解的AspectJ开发。 二、 实验内容 1、按图所示的类图结构,设计接口及其实现类,并完成另外两附加要求:(1)日志功能:在程序执行期间追踪正在发生的...
使用Spring 4.0.x和Gradle 24 2.4.3项目模块 25 核心 - spring-security-core.jar 25 远程处理 - spring-security-remoting.jar 25 Web - spring-security-web.jar 25 配置 - spring-security-config.jar 26 LDAP - ...
1.8 小结 第2章 快速入门 2.1 实例功能概述 2.1.1 比Hello World更适用的实例 2.1.2 实例功能简介 2.2 环境准备 2.2.1 创建库表 2.2.2 建立工程 2.2.3 类包及Spring配置文件规划 2.3 持久层 2.3.1 建立领域对象 ...
一共四个,其中pdf 三个包,源码一个包 第一章 J2EE快速入门 1.1 J2EE概述 1.1.1 J2EE的来源 1.1.2 J2EE整体框架 1.1.3 从J2EE到JavaEE 1.2 J2EE组件 1.2.1 客户端组件 1.2.2 Web组件 ...15.13 小结
第一部分 Spring基础 第1章 开始Spring之旅 1.1 为什么使用Spring 1.1.1 J2EE开发者的一天 1.1.2 Spring的承诺 1.2 Spring是什么 ... 1.3 开始Spring之旅 ... 1.6 Spring比较 ... 11.6 小结
文档包含各种重要命令参数的解析、具体的原理、具体的代码分析、实现资源也从数据库进行验证。在别人资料基础上做了的优化和总结。绝对物有所值。
一共四个,其中pdf 三个包,源码一个包 第一章 J2EE快速入门 1.1 J2EE概述 1.1.1 J2EE的来源 1.1.2 J2EE整体框架 1.1.3 从J2EE到JavaEE 1.2 J2EE组件 1.2.1 客户端组件 1.2.2 Web组件 ...15.13 小结
2.5小结 4 3 系统需求分析 5 3.1引言 5 3.2 功能性需求分析 5 3.3性能需求分析 6 3.4结果与讨论 6 3.5小结 6 4 系统详细设计 7 4.1引言 7 4.2系统功能模块 7 4.3数据库设计 8 4.3.1 数据库的逻辑设计 8 4.3.2 数据库...
目录 第一部分spring的核心 第1章开始spring之旅 1.1spring是什么 1.2开始spring之旅 1.3理解依赖注入 ...1.5小结 ...2.4.2混合使用自动和手动装配 ...2.5.3初始化和销毁bean ...2.6小结 ...3.1声明父bean和子bean ...b.4小结
5.2.4. 小结 5.3. 验证 5.3.1. 什么是Spring Security 的验证呢? 5.3.2. 直接设置SecurityContextHolder 的内容 5.4. 在web 应用中验证 5.4.1. ExceptionTranslationFilter 5.4.2. ...
第一部分 Spring的核心 第1章 开始Spring之旅 1.1 Spring是什么 1.2 开始Spring之旅 1.3 理解依赖注入 1.3.1 依赖注入 1.3.2 DI应用 1.3.3 企业级应用中的依赖注入 1.4 应用AOP ...B.4 小结
第一部分 Spring的核心 第1章 开始Spring之旅 1.1 Spring是什么 1.2 开始Spring之旅 1.3 理解依赖注入 1.3.1 依赖注入 1.3.2 DI应用 1.3.3 企业级应用中的依赖注入 1.4 应用AOP ...B.4 小结