06springMVC数据验证
- u 声明式数据验证
- u 内置的验证约束和注解
- u 错误消息
- u 功能处理方法上多个验证参数的处理
- u 异常处理的支持
1 声明式数据验证
Spring3开始支持JSR-303验证框架,JSR-303支持XML风格的和注解风格的验证,接下来我们首先看一下如何使用Spring的验证功能。
1、添加jar包
此处使用Hibernate-validator实现(版本:hibernate-validator-4.3.0.Final-dist.zip),将如下jar包添加到classpath(WEB-INF/lib下即可):
- dist/lib/required/validation-api-1.0.0.GA.jar JSR-303规范API包
- dist/hibernate-validator-4.3.0.Final.jar Hibernate 参考实现
- 还需要加入jboss-logging-3.1.0.CR2.jarFormatter SPI简介
2、在Spring配置中添加对JSR-303验证框架的支持
<!-- 以下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>
3、在Spring配置中添加message配置
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages"/>
<property name="fileEncodings" value="utf-8"/>
<property name="cacheSeconds" value="120"/>
</bean>
username.not.empty= =\u7528\u6237\u59D3\u540D\u4E0D\u80FD\u4E3A\u7A7A在src下放一个messages.properties,里面的内容是:
这是已经转义的,原始的信息是:用户姓名不能为空
将校验器注入到处理器适配器中
<!-- 校验器注入到处理器适配器中 --> <mvc:annotation-driven validator="validator"/>
使用JSR-303验证框架注解为模型对象指定验证信息。
4、 HelloWorld的Model
public class UserModel {
@NotNull(message="{username.not.empty}")
private String username;
省略get/set……
}
通过@NotNull指定此username字段不允许为空,当验证失败时将从之前指定的messageSource中获取“username.not.empty”对于的错误信息,此处只有通过“{错误消息键值}”格式指定的才能从messageSource获取。
5、 HelloWorld的Controller
@Controller
public class HelloWorldController {
@RequestMapping("/validate/hello")
public String validate(@Valid @ModelAttribute("user") UserModel user, Errors errors) {
if (errors.hasErrors()) {
return "validate/error";
}
return "validate/success";
}
}
说明:错误对象的代表者是Errors接口,并且提供了几个实现者,在Spring Web MVC中我们使用的是如下实现:Errors、BindingResult、BindException等通过在命令对象上注解@Valid来告诉Spring MVC此命令对象在绑定完毕后需要进行JSR-303验证,如果验证失败会将错误信息添加到errors错误对象中
6、 HelloWorld的验证失败后需要展示的页面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<form:form commandName="user">
<form:errors path="*" cssStyle="color:red"></form:errors><br/>
</form:form>
可以去测试啦,不给UserModel传递name值看看效果。
测试地址:
http://localhost:8088/06springMVC/validate/hello?username=999
和
http://localhost:8088/06springMVC/validate/hello
2 内置的验证约束和注解
u @AssertFalse
验证的数据类型:Boolean,boolean
说明:验证注解的元素值是false
u @AssertTrue
验证的数据类型:Boolean,boolean
说明:验证注解的元素值是true
u @NotNull
验证的数据类型:任意类型
说明:验证注解的元素值不是null
u @Null
验证的数据类型:任意类型
说明:验证注解的元素值是null
u @Min(value=值)
验证的数据类型:BigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存储的是数字)子类型
说明:验证注解的元素值大于等于@Min指定的value值
u @Max(value=值)
验证的数据类型:和@Min要求一样
说明:验证注解的元素值小于等于@Max指定的value值
u @DecimalMin(value=值)
验证的数据类型:和@Min要求一样
说明:验证注解的元素值大于等于@ DecimalMin指定的value值
u @DecimalMax(value=值)
验证的数据类型:和@Min要求一样
说明:验证注解的元素值小于等于@ DecimalMax指定的value值
u @Digits(integer=整数位数, fraction=小数位数)
验证的数据类型:和@Min要求一样
说明:验证注解的元素值的整数位数和小数位数上限
u @Size(min=下限, max=上限)
验证的数据类型:字符串、Collection、Map、数组等
说明:验证注解的元素值的在min和max(包含)指定区间之内,如字符长度、集合大小
u @Past
验证的数据类型:java.util.Date,java.util.Calendar,Joda Time类库的日期类型
说明:验证注解的元素值(日期类型)比当前时间早
u @Future
验证的数据类型:与@Past要求一样
说明:验证注解的元素值(日期类型)比当前时间晚
u @NotBlank
验证的数据类型:CharSequence子类型
说明:验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty
@NotBlank只应用于字符串且在比较时会去除字符串的首位空格
u @Length(min=下限, max=上限)
验证的数据类型: CharSequence子类型
说明:验证注解的元素值长度在min和max区间内
u @NotEmpty
验证的数据类型:CharSequence子类型、Collection、Map、数组
说明:验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
u @Range(min=最小值, max=最大值)
验证的数据类型:BigDecimal,BigInteger,CharSequence, byte, short, int, long等原子类型和包装类型
说明:验证注解的元素值在最小值和最大值之间
u @Email(regexp=正则表达式,flag=标志的模式)
验证的数据类型:CharSequence子类型(如String)
说明:验证注解的元素值是Email,也可以通过regexp和flag指定自定义的email格式
u @Pattern(regexp=正则表达式,flag=标志的模式)
验证的数据类型:String,任何CharSequence的子类型
说明:验证注解的元素值与指定的正则表达式匹配
u @Valid
验证的数据类型:任何非原子类型
说明:指定递归验证关联的对象;如用户对象中有个地址对象属性,如果想在验证用户对象时一起验证地址对象的话,在地址对象上加@Valid注解即可级联验证
注意:
此处只列出Hibernate Validator提供的大部分验证约束注解,请参考hibernatevalidator官方文档了解其他验证约束注解和进行自定义的验证约束注解定义
3 错误消息
当验证出错时,我们需要给用户展示错误消息告诉用户出错的原因,因此我们要为验证约束注解指定错误消息。错误消息是通过在验证约束注解的message属性指定。验证约束注解指定错误消息有如下两种方式:
1、硬编码错误消息;
2、从资源消息文件中根据消息键读取错误消息。
u 硬编码错误消息
直接在验证约束注解上指定错误消息,如下所示:
@NotNull(message = "用户名不能为空")
@Length(min=5, max=20, message="用户名长度必须在5-20之间")
@Pattern(regexp = "^[a-zA-Z_]\\w{4,19}$", message = "用户名必须以字母下划线开头,可由字母数字下划线组成")
private String username;
如上所示,错误消息使用硬编码指定,这种方式是不推荐的,因为在如下场景是不适用的:
1、在国际化场景下,需要对不同的国家显示不同的错误消息;
2、需要更换错误消息时是比较麻烦的,需要找到相应的类进行更换,并重新编译发布。
u 从资源消息文件中根据消息键读取错误消息
这个最为推荐的方式就是直接使用Spring的MessageSource Bean进行消息的匹配和管理,前面的案例就是使用的这个方式,这儿就不赘述了。
4 功能处理方法上多个验证参数的处理
当我们在一个功能处理方法上需要验证多个模型对象时,需要通过如下形式来获取验证结果:
@RequestMapping("/validate/multi")
public String multi(
@Valid @ModelAttribute("a") A a, BindingResult aErrors,
@Valid @ModelAttribute("b") B b, BindingResult bErrors) {
if(aErrors.hasErrors()) { //如果a模型对象验证失败
return "validate/error";
}
if(bErrors.hasErrors()) { //如果a模型对象验证失败
return "validate/error";
}
return " validate/success";
}
每一个模型对象后边都需要跟一个Errors或BindingResult对象来保存验证结果,其方法体内部可以使用这两个验证结果对象来选择出错时跳转的页面。
在错误页面,需要针对不同的模型来显示错误消息:
<form:form commandName="a">
<form:errors path="*" cssStyle="color:red"></form:errors><br/>
</form:form>
<form:form commandName="b">
<form:errors path="*" cssStyle="color:red"></form:errors><br/>
</form:form>
然后就可以测试了。
5 异常处理的支持
Spring Web MVC对异常处理的支持有三种方式:
1:一种是直接实现自己的HandlerExceptionResolver ,通常用来实现全局异常控制
2:Spring Web MVC已经有了一个缺省的实现:SimpleMappingExceptionResolver,
3:用注解的方式实现一个专门用于处理异常的Controller——ExceptionHandler,通常用来在Controller内部实现更个性化点异常处理方式,灵活性更高。
u 自定义实现的方式,只需要实现HandlerExceptionResolver接口即可,示例如下:
public class MyExceptionHandler implements HandlerExceptionResolver {
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
if (ex instanceof NullPointerException) {
// 这里就写如何处理,比如:记日志
System.out.println("now is NullPointer 01");
} else if (ex instanceof ArrayIndexOutOfBoundsException) {
// 这里就写如何处理,比如:记日志
}
return new ModelAndView("/error/nullPage1");
}
}
上述类需要在spring的配置文件中配置,示例如下:
<bean id="myExceptionHandler" class="cn.javass.springmvc.exception.MyExceptionHandler"/>
说明:
1:上述示例的resolveException方法的第四个参数,就是具体的例外类型
2:如果该方法返回了null,则Spring会继续寻找其他的实现了HandlerExceptionResolver 接口的Bean。也就是说,Spring会搜索 所有注册在其环境中的实现了HandlerExceptionResolver接口的Bean,逐个执行,直到返回了一个ModelAndView对象。
典型的异常显示页面示例如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<% Exception ex = (Exception) request.getAttribute("ex"); %>
<H2>Exception: <%=ex.getMessage()%></H2>
This is my nullPage1 page.
<br>
</body>
</html>
测试方法示例:
@RequestMapping("test")
public void test() {
throw new NullPointerException("出错了!");
}
u 当然我们也可以直接使用Spring提供的SimpleMappingExceptionResolver类,示例如下:
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 定义默认的异常处理页面,当该异常类型的注册时使用-->
<property name="defaultErrorView" value="exception"></property>
<!-- 定义异常处理页面用来获取异常信息的变量名,默认名为exception -->
<property name="exceptionAttribute" value="ex"></property>
<!-- 定义需要特殊处理的异常,用类名或完全路径名作为key,异常显示的页面名作为值-->
<property name="exceptionMappings">
<props>
<prop key="NullPointerException">error/nullPage3</prop>
<prop key="ArrayIndexOutOfBoundsException">error/ArrayIndexOutOfBoundsPage</prop>
</props>
</property>
</bean>
说明:出了错过后,例外信息会以ex为key存放在request属性里面,因此在错误页面就可以通过request的属性取到例外对象了
u 基于@ExceptionHandler的异常处理
该方法需要定义在Controller内部,然后创建一个方法并用@ExceptionHandler注解来修饰用来处理异常,这个方法基本和@RequestMapping修饰的方法差不多,只是可以多一个类型为Exception的参数,@ExceptionHandler中可以添加一个或多个异常的类型,如果为空的话则认为可以触发所有的异常类型错误。
Controller示例如下:
@ExceptionHandler(value = { NullPointerException.class, ArrayIndexOutOfBoundsException.class })
public String exceptionExecute(Exception ex, HttpServletRequest request) {
request.setAttribute("ex", ex);
if (ex instanceof NullPointerException) {
// 这里就写如何处理,比如:记日志
System.out.println("now is NullPointer2");
return "error/nullPage2";
} else if (ex instanceof ArrayIndexOutOfBoundsException) {
// 这里就写如何处理,比如:记日志
}
return "error/nullPage2";
}
u 三种处理方式都有的运行顺序
1:优先在自己Controller里面寻找@ExceptionHandler,看能不能处理
2:如果不能,然后在Spring中,寻找实现HandlerExceptionResolver 的Bean
3:对于多个都能处理的Bean,则按照配置的先后顺序进行处理
4:只要有一个能处理,不返回null,那么就结束
06springMVC数据验证的更多相关文章
- 我这么玩Web Api(二):数据验证,全局数据验证与单元测试
目录 一.模型状态 - ModelState 二.数据注解 - Data Annotations 三.自定义数据注解 四.全局数据验证 五.单元测试 一.模型状态 - ModelState 我理解 ...
- MVC 数据验证
MVC 数据验证 前一篇说了MVC数据验证的例子,这次来详细说说各种各样的验证注解.System.ComponentModel.DataAnnotations 一.基础特性 一.Required 必填 ...
- kpvalidate开辟验证组件,通用Java Web请求服务器端数据验证组件
小菜利用工作之余编写了一款Java小插件,主要是用来验证Web请求的数据,是在服务器端进行验证,不是简单的浏览器端验证. 小菜编写的仅仅是一款非常初级的组件而已,但小菜为它写了详细的说明文档. 简单介 ...
- MVC3 数据验证用法之密码验证设计思路
描述:MVC数据验证使用小结 内容:display,Required,stringLength,Remote,compare,RegularExpression 本人最近在公司用mvc做了一个修改密码 ...
- jQuery MiniUI开发系列之:数据验证
在开发应用系统界面时,往往需要进行很多.复杂的数据验证,当填写的数据符合规定,才能提交保存. jQuery MiniUI提供了比较完美的表单数据验证和错误显示的方式. 常见的表单控件,都有一个验证事件 ...
- AngularJS快速入门指南14:数据验证
thead>tr>th, table.reference>tbody>tr>th, table.reference>tfoot>tr>th, table ...
- atitit.数据验证--db数据库数据验证约束
atitit.数据验证--db数据库数据验证约束 1. 为了加强账户数据金额的安全性,需要增加验证字段..1 2. 创建帐户1 3. 更改账户2 4. ---code3 5. --fini4 1. 为 ...
- MVC数据验证原理及自定义ModelValidatorProvider实现无编译修改验证规则和错误信息
Asp.net MVC中的提供非常简单易用的数据验证解决方案. 通过System.ComponentModel.DataAnnotations提供的很多的验证规则(Required, StringLe ...
- MVC 数据验证[转]
前一篇说了MVC数据验证的例子,这次来详细说说各种各样的验证注解. 一.基础特性 一.Required 必填选项,当提交的表单缺少该值就引发验证错误. 二.StringLength 指定允许的长度 指 ...
随机推荐
- Ubuntu下FileZilla的安装(转载)
转自:http://os.51cto.com/art/201103/247564.htm FileZilla是一个免费而且开源的FTP客户端软件,共有两种版本:客户端版本.服务器版本.FileZill ...
- P3199 [HNOI2009]最小圈
传送门 据rqy说有这么一个结论\[ans=\min_{v \in V,F_n(v)\neq \infty} \max_{0 \leq k \leq n - 1} \left[\frac{F_n(v) ...
- [Swift通天遁地]九、拔剑吧-(14)创建更美观的景深视差滚动效果
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- C# 工厂单例
public class BusinessFactory { private static BusinessFactory instance = null; pri ...
- Android布局属性LayoutParams的理解
在一次笔试中搞混LayoutParams的用法,特来总结一番: LayoutParams继承于Android.View.ViewGroup.LayoutParams.LayoutParams相当于一个 ...
- ACM_夏天到了,又到了出游的季节
夏天到了,又到了出游的季节 Time Limit: 2000/1000ms (Java/Others) Problem Description: QWER最近无心打代码,于是带着n套衣服出去浪.但是每 ...
- python导入包出错:ImportError: No module named XXXXX
python中,每个py文件被称之为模块,每个具有__init__.py文件的目录被称为包.只要模块或者包所在的目录在sys.path中,就可以使用import 模块或import 包来使用. 如果想 ...
- mysql视图的操作
一.创建视图的语法形式 CREATE VIEW view_name AS 查询语句 ; 使用视图 SELECT * FROM view_name ; 二.创建各种视图 1.封装实现查询常量语句的视图, ...
- Algebrizer
Microsoft SQL Server 2012 Internals 把 SQL 语句的处理分为四个阶段,分别是 解析.绑定.优化.执行,如图所示: 解析(Parse)主要是语法分析,比较简 ...
- xcode常用的快捷键
按键 描述 command+[ 左移代码块 command+] 右移代码块 Tab键 接受代码自动完成提示 Esc键 显示代码提示菜单 command+方向left键 移动光标到本行行首 comman ...