浅析调用JSR303的validate方法, 验证失败时抛出ConstraintViolationException
废话不多说,直接进入正题:如何使用JSR303的validate,进行数据校验,失败后直接抛出异常加入流转信息中,并在form页面提示出来。
首先我们为了启用验证,需要向
项目中添加Bean验证的实现。本列选择Hibernate Validator框架来提供验证功能。可以像下面的示例那样将该项目作为一个Maven依赖添加到当前项目中。此外,Hibernate Validator会将Bean Validation API作为一个船只依赖添加到项目中。
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.1.Final</version>
</dependency>
在表单页面引入如下标签:
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
然后使用该标签下的form:form进行数据验证的绑定
<form:form id="inputForm" modelAttribute="article" action="${ctx}/cms/article/save" method="post" class="form-horizontal">
<div class="control-group">
<label class="control-label">摘要:</label>
<div class="controls">
<form:textarea path="description" htmlEscape="false" rows="4" maxlength="200" class="input-xxlarge"/>
</div>
</div>
<div class="form-actions">
<shiro:hasPermission name="cms:article:edit"><input id="btnSubmit" class="btn btn-primary" type="submit" value="保 存"/> </shiro:hasPermission>
<input id="btnCancel" class="btn" type="button" value="返 回" onclick="history.go(-1)"/>
</div>
</form:form>
如上我只是简单举了一个字段为description(简介/描述)的数据验证例子 其实这里的maxlength="200",我们完全可以忽略它,因为前段的验证始终是不安全的,而且我们在后台进行的验证因为整合了jsr303变的异常的简洁,我们只需要在需要验证的
表单实体的get方法上加上一行注解:
@Length(min=0, max=5)
public String getDescription() {
return description;
}
//这行注解的意思是最小长度是0,最大长度是5
然后在控制层写上验证失败加入流转信息并返回form页的代码:
@RequestMapping(value = "save")
public String save(Article article, Model model, RedirectAttributes redirectAttributes) {
if (!beanValidator(model, article)){
return form(article, model);
}
articleService.save(article);
addMessage(redirectAttributes, "保存文章'" + StringUtils.abbr(article.getTitle(),50) + "'成功");
String categoryId = article.getCategory()!=null?article.getCategory().getId():null;
return "redirect:" + adminPath + "/cms/article/?repage&category.id="+(categoryId!=null?categoryId:"");
}
我们进入beanValidator(model,article)这个方法一探究竟:
/**
* 服务端参数有效性验证
* @param object 验证的实体对象
* @param groups 验证组
* @return 验证成功:返回true;严重失败:将错误信息添加到 message 中
*/
protected boolean beanValidator(Model model, Object object, Class<?>... groups) {
try{
BeanValidators.validateWithException(validator, object, groups);
}catch(ConstraintViolationException ex){
List<String> list = BeanValidators.extractPropertyAndMessageAsList(ex, ": ");
list.add(0, "数据验证失败:");
addMessage(model, list.toArray(new String[]{}));
return false;
}
return true;
}
/**
* JSR303 Validator(Hibernate Validator)工具类.
*
* ConstraintViolation中包含propertyPath, message 和invalidValue等信息.
* 提供了各种convert方法,适合不同的i18n需求:
* 1. List<String>, String内容为message
* 2. List<String>, String内容为propertyPath + separator + message
* 3. Map<propertyPath, message>
*
* 详情见wiki: https://github.com/springside/springside4/wiki/HibernateValidator
* @author calvin
* @version 2013-01-15
*/
public class BeanValidators { /**
* 调用JSR303的validate方法, 验证失败时抛出ConstraintViolationException.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void validateWithException(Validator validator, Object object, Class<?>... groups)
throws ConstraintViolationException {
Set constraintViolations = validator.validate(object, groups);
if (!constraintViolations.isEmpty()) {
throw new ConstraintViolationException(constraintViolations);
}
} /**
* 辅助方法, 转换ConstraintViolationException中的Set<ConstraintViolations>为List<propertyPath +separator+ message>.
*/
public static List<String> extractPropertyAndMessageAsList(ConstraintViolationException e, String separator) {
return extractPropertyAndMessageAsList(e.getConstraintViolations(), separator);
} }
/**
* 添加Model消息
* @param message
*/
protected void addMessage(Model model, String... messages) {
StringBuilder sb = new StringBuilder();
for (String message : messages){
sb.append(message).append(messages.length>1?"<br/>":"");
}
model.addAttribute("message", sb.toString());
}
最后我们要做的就是在form页面把model中的错误信息展示出来就行了:
<script type="text/javascript">top.$.jBox.closeTip();</script>
<c:if test="${not empty content}">
<c:if test="${not empty type}"><c:set var="ctype" value="${type}"/></c:if><c:if test="${empty type}"><c:set var="ctype" value="${fn:indexOf(content,'失败') eq -1?'success':'error'}"/></c:if>
<div id="messageBox" class="alert alert-${ctype} hide"><button data-dismiss="alert" class="close">×</button>${content}</div>
<script type="text/javascript">if(!top.$.jBox.tip.mess){top.$.jBox.tip.mess=1;top.$.jBox.tip("${content}","${ctype}",{persistent:true,opacity:0});$("#messageBox").show();}</script>
</c:if>
例子展示如下:

这种验证方法是每次都会向服务器发送一次请求,如果一些简单的验证不需要向后台区请求,我们可以使用自定义的validate在前端完成简单的数据验证:
$("#inputForm").validate({
submitHandler: function(form){
if ($("#categoryId").val()==""){
$("#categoryName").focus();
top.$.jBox.tip('请选择归属栏目','warning');
}else if (CKEDITOR.instances.content.getData()=="" && $("#link").val().trim()==""){
top.$.jBox.tip('请填写正文','warning');
}else{
loading('正在提交,请稍等...');
form.submit();
}
},
errorContainer: "#messageBox",
errorPlacement: function(error, element) {
$("#messageBox").text("输入有误,请先更正。");
if (element.is(":checkbox")||element.is(":radio")||element.parent().is(".input-append")){
error.appendTo(element.parent().parent());
} else {
error.insertAfter(element);
}
}
});

浅析调用JSR303的validate方法, 验证失败时抛出ConstraintViolationException的更多相关文章
- List 调用 remove 方法时抛出 java.lang.UnsupportedOperationException 异常原因
原因 使用 Arrays.asList(arr) 转换的 List 并不能进行 add 和 remove 操作. Arrays.asList(arr) 返回的类型是 Aarrays$Arr ...
- java异常处理:建立exception包,建立Bank类,类中有变量double balance表示存款,Bank类的构造方法能增加存款,Bank类中有取款的发方法withDrawal(double dAmount),当取款的数额大于存款时,抛出InsufficientFundsException,取款数额为负数,抛出NagativeFundsException,如new Bank(100),
建立exception包,建立Bank类,类中有变量double balance表示存款,Bank类的构造方法能增加存款,Bank类中有取款的发方法withDrawal(double dAmount ...
- 为 jquery validate 添加验证失败回调
转载自:https://blog.csdn.net/huang100qi/article/details/52619227 1. jquery Validation Plugin - v1.15.1 ...
- Struts(二十四):短路验证&重写实现转换验证失败时短路&非字段验证
短路验证: 若对一个字段使用多个验证器,默认情况下会执行所有的验证.若希望前面的验证器没有通过,后面的验证器就不再执行,可以使用短路验证. 1.如下拦截器,如果输入字符串,提交表单后,默认是会出现三个 ...
- 调用远程主机上的 RMI 服务时抛出 java.rmi.ConnectException: Connection refused to host: 127.0.0.1 异常原因及解决方案
最近使用 jmx 遇到一个问题,client/server 同在一台机器上,jmx client能够成功连接 server,如果把 server 移植到另一台机器上192.168.134.128,抛出 ...
- 在自定义的js验证规则中调用magento的VarienForm方法验证表单
js部分<script type="text/javascript"> //<![CDATA[ var loginForm = new VarienForm('l ...
- mixare的measureText方法在频繁调用时抛出“referencetable overflow max 1024”的解决方式
这几天在搞基于位置的AR应用,採用了github上两款开源项目: mixare android-argument-reality-framework 这两个项目实现机制大致同样.我选取的是androi ...
- Redis出现多线程调用时抛出 [B cannot be cast to java.lang.Long] 异常
原因分析: 多个线程同时调用了同一个jedis对象,导致内存数据被多个线程竞争,产生数据混乱 (或者大家都用通一个redis获取同一个实例,登录同一个账号使用缓存时报错) 解决方案:每个线程都new出 ...
- CAD调试时抛出“正试图在 os 加载程序锁内执行托管代码。不要尝试在 DllMain 或映像初始化函数内运行托管代码”异常的解决方法
这些天重装了电脑Win10系统,安装了CAD2012和VS2012,准备进行软件开发.在调试程序的时候,CAD没有进入界面就抛出 “正试图在 os 加载程序锁内执行托管代码.不要尝试在 DllMain ...
随机推荐
- .net的retrofit--WebApiClient底层篇
前言 本篇文章的内容是WebApiClient底层说明,也是WebApiClient系列接近尾声的一篇文章,如果你没有阅读过之前的的相关文章,可能会觉得本文章的内容断层,WebApiClient系列文 ...
- vim中的批量替换
VI中的批量替换 1) 文件内全部替换: :%s#abc#123#g (如文件内有#,可用/替换,:%s/abc/123/g) --注:把abc替换成123 (或者: %s/str ...
- reduce 方法 (Array) (JavaScript)
对数组中的所有元素调用指定的回调函数.该回调函数的返回值为累积结果,并且此返回值在下一次调用该回调函数时作为参数提供. 语法 array1.reduce(callbackfn[, in ...
- linux命令 uname -r 和 uname -a 的解释与演示
1.uname -r : 显示操作系统的发行版号2.uname -a :显示系统名.节点名称.操作系统的发行版号.内核版本等等. 系统名:Linux 节点名称: iZ2zeeailqvwws5dcui ...
- UEP-find查询
实体类: @Entity @Table(name = "xxxxx") public class WzInitializeStoreInfo extends EntityBean{ ...
- Video Target Tracking Based on Online Learning—深度学习在目标跟踪中的应用
摘要 近年来,深度学习方法在物体跟踪领域有不少成功应用,并逐渐在性能上超越传统方法.本文先对现有基于深度学习的目标跟踪算法进行了分类梳理,后续会分篇对各个算法进行详细描述. 看上方给出的3张图片,它们 ...
- [数据预处理]-中心化 缩放 KNN(一)
据预处理是总称,涵盖了数据分析师使用它将数据转处理成想要的数据的一系列操作.例如,对某个网站进行分析的时候,可能会去掉 html 标签,空格,缩进以及提取相关关键字.分析空间数据的时候,一般会把带单位 ...
- DEDE中如何过滤掉Html标签,并且截取字符串长度
在dede标签中只要使用2个函数就可以. [field:body function="cn_substr(Html2text(@me),80)"/] Html2text()函数是去 ...
- NSString拼接字符串
NSString* string; // 结果字符串 02 NSString* string1, string2; //已存在的字符串,需要将string1和string2连接起来 03 04 / ...
- Hadoop集群的JobHistoryServer详解(转载)
Hadoop自带了一个历史服务器,可以通过历史服务器查看已经运行完的Mapreduce作业记录,比如用了多少个Map.用了多少个Reduce.作业提交时间.作业启动时间.作业完成时间等信息.默认情况下 ...