Spring验证的错误返回------BindingResult

参考资料:http://www.mkyong.com/spring-mvc/spring-mvc-form-errors-tag-example/

<%Enumeration<String> enums=request.getAttributeNames();
while(enums.hasMoreElements()){

String key=enums.nextElement();
if(key.equals("org.springframework.validation.BindingResult.改为自己spring表单名")){
BeanPropertyBindingResult valuess=(BeanPropertyBindingResult)request.getAttribute(key);

out.print("=========######===========<br/>");
for(FieldError or:valuess.getFieldErrors()){

out.print(or.getCode()+"<br/>");
out.print("------------------------<br/>");
//out.print(or.getDefaultMessage()+"<br/>");
for(String codes:or.getCodes()){
out.print(codes+"<br/>");
}

// out.print(or.getArguments()+"<br/>");
out.print(or.getField()+"<br/>");
out.print(or.getRejectedValue()+"<br/>");

out.print("====================<br/>");
}

out.print("====================<br/>");
}

}

}
%>

最近做的一个项目使用了 Spring MVC3, 其中验证也是使用Spring的 validate 框架, 但不是全部。

我们 只是使用了org.springframework.validation.Errors, org.springframework.validation.BindingResult 来将验证错误信息返回到JSP页面。因为Spring提供了<form:errors>标签来显示BindingResult对象里的错误信 息, 并且这个验证框架还支持国际化, errorCode对应的语言文字放到工程的message资源文件就好了。

下面是一个简单的注册账户的例子:包括三个文件:JSP, AccountValidator和AccountValidator。

1. 首先是JSP页面:addAccount,jsp的表单

<form:form modelAttribute="accountVo" action="${actionUrl}" method="post"> 
            <form:hidden path="id"  readonly=“readonly”/>

<form:input path="email" size="30" onblur="checkEmail();"/> //path的值必须和accountVo这个对象的属性一致

<form:errors path="email" cssClass="errorMsg"></form:errors>

//这里省略了表单的其他元素, 直接来提交按钮

<input type=" button"  id="saveAccount"  value='<fmt:message key="button.next" />' onclick="submitAccount ('accountVo')"/>

//这里完全可以使用type=“submit”, 这里使用button可以截获提交事件, 并在提交之前先做JS层面的验证

</form:form>

Note: 使用上面这些标签, 必须引入Spring 的 form标签库:<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

大家还看到我们使用了JSTL的fmt标签库(国际化), 这个也要引入<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>, 其实我们也完全可以用<form message>标签来做国际化的。这里我还想说一个东西:readonly这个属性根本起不到只读的作用, 完全可以被修改,但是使用disable属性后,这个表单元素就无法放到accountVo这个对象并提交了, 纠结!

2. 这里是个不完整的验证类AccountValidator, 注意,我们没有实现Validator接口

public class AccountValidator { 
    public void validate(AccountVo accountVo, Errors errors) { 
        String email = accountVo.getEmail(); 
        if (!StringUtils.hasLength(email)) { 
             errors.rejectValue("email", "validate.email.empty", "邮箱不能为空");//这个函数有好几个重载的变体 
        } 
   } 
}

Note: Errors这个接口有好几个rejectValue()函数, 它们是可以支持国际化的。 比如, 上面这个例子表示, 错误的字段(filed)是“email”, errorCode是“validate.email.empty”, 与资源文件对应, 第三个是defaultMessage。很多国际化当中会带有参数, rejectValue其中的一个重载函数就是 rejectValueString field, String errorCode, Object[] errorArgs, String defaultMessage)。

3. 最后是AccountController

@Controller//基于注解, 声明这是一个controller 
@RequestMapping(value="/account") //表示总的路径 
@SessionAttributes("account") //表示account对象将会存入session当中, //默认情况下model.addAttribute(account)将会把account对象放入request当中, 并且属性名为“account” 
public class AccountFormController {

@RequestMapping(value = "/add", method = RequestMethod.POST) 
    public String addAccount( @ModelAttribute("accountVo") AccountVo accountVo
             BindingResult result, //这里面,BindResult result必须紧跟着前面的@ModelAttribute, 否则会出错

HttpServletResponse response, 
            HttpSession session, Model model) { 
        log.debug(accountVo.toString()); 
         
        if(isExist(accountVo)){ 
            log.debug("Opps, 这个email已经注册过了!"); 
             result.rejectValue("email", "misFormat", "这个email已经注册过了!"); 
            return "account/addAccount"; 
        }else{ 
            new AccountValidator().validate(accountVo, result); 
            if( result.hasErrors()){ 
                log.debug("表单数据有误, 重新填写"+accountVo); 
                model.addAttribute("accountVo",accountVo);//把accountVo对象返回到页面, 这样不至于表单被清空了 
                return "account/addAccount";//返回到注册页面,同时,这里会自动将验证错误信息返回到JSP页面, 怎么返回呢?看后面! 
            } 
            //这里会做很多数据库的操作, 省略 
       }

} //end of login()

}//end of controller

Note: 这里需要特别注意几个问题:1.函 数形参 BindResult result 必须紧跟着前面的@ModelAttribute, 否则会出异常; 2. @ModelAttribute("accountVo") AccountVo accountVo, 这个参数与JSP页面的<form:form modelAttribute="accountVo" action="${actionUrl}" method="post">对应

4. 进阶一下, 看看验证错误信息对象是怎么传递到页面的

这 一切看起来都很完美, 但是有时候出于设计的原因, 我们不得不使用redirect, 对, 就是重定向! 就是这个东西让我对Spring MVC有了一点不好的印象, 特别是结合了sitemesh之后。这个先打住, 咱们还是说验证错误怎么传给重定向之后的JSP页面吧。

其实也简单, 咱们可以先把错误对象放入session当中, 然后在另一个Controller里把它取出来, 然后再返回到相应的JSP页面就行了!

对!但是,这里要注意了, BindingResult这个对象是自动传入JSP的, 我们不知道应该把它放在request里面呢还是session里面, 或者其他的地方, 以及属性名叫什么。这个就是我昨天晚上纠结的问题, 最后看了一下Spring 的源代码, 终于稍微清楚了一点儿。下面直接上代码,然后解释。

if(session.getAttribute("BindingResult.accountVo") != null){ 
            //放到session和request里面, 不论attr name设置成什么都不行 
            //只有这样才能把bindingresult的错误信息传到JSP页面 
            String errorAttrName = " org.springframework.validation.BindingResult.accountenterpriseVo"; 
             model.addAttribute(errorAttrName, session.getAttribute("BindingResult.accountVo")); 
            session.removeAttribute("BindingResult.enterpriseVo");

}

首先, 验证错误对象 BindingResult 必须放入 org.springframework.ui. Model 当中返回给JSP页面。放到request和session当中都没用。

第二,这个属性名是 BindingResult.getClass().getName + “.” + targetName, 也就是上面那一长串, 其中targerName对应着JSP页面的表单的modelAttribute, 即<form:form modelAttribute="accountVo" action="${actionUrl}" method="post">中的accountVo。 对了, 顺便说一下, accountVo同时还是表单的id, 大家可以用firefox的firebug查看页面元素。<form:error>标签也会被翻译成

<span class="errorMsg" id="email.errors">邮箱格式不正确!</span> //如果是英文浏览器, “邮箱格式不正确!”就会使英文版本的。

好的, 就先写到这里了。

Spring验证的错误返回------BindingResult的更多相关文章

  1. Spring Boot API 统一返回格式封装

    今天给大家带来的是Spring Boot API 统一返回格式封装,我们在做项目的时候API 接口返回是需要统一格式的,只有这样前端的同学才可对接口返回的数据做统一处理,也可以使前后端分离 模式的开发 ...

  2. spring boot 解决后台返回 json 到前台中文乱码之后出现返回json数据报错 500:no convertter for return value of type

    问题描述 spring Boot 中文返回给浏览器乱码 解析成问号?? fastJson jackJson spring boot 新增配置解决后台返回 json 到前台中文乱码之后,出现返回json ...

  3. egg框架实现表单验证及获取验证的错误信息

    最近再看egg框架 是阿里今年开源的一款基于nodejs的mvc架构的web框架 感兴趣的同学可以看看 因为之前一直做php的关系 在tp,yii,laravel这些框架中对于前台发送的数据,模型里都 ...

  4. 自定义 serializers.ValidationError 的错误返回

    在使用DRF进行反序列过程中,总是需要校验字段,然后返回错误结果.可以使用默认的自定义校验项,也可以自定义校验项.而默认的自定义校验项总是差强人意. 版本 Django 2.2.3 Python 3. ...

  5. TCP connect的错误返回值

    如果是TCP套接字,调用connect函数将激发TCP三次握手过程,而且仅在连接建立成功或出错时返回,其中错误返回可能有下面几种情况: (1)若TCP客户没有收到SYN分节的响应,则返回ETIMEDO ...

  6. [原创]java WEB学习笔记71:Struts2 学习之路-- struts2常见的内建验证程序及注意点,短路验证,非字段验证,错误消息的重用

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  7. Spring MVC 3.0 返回JSON数据的方法

    Spring MVC 3.0 返回JSON数据的方法1. 直接 PrintWriter 输出2. 使用 JSP 视图3. 使用Spring内置的支持// Spring MVC 配置<bean c ...

  8. jQuery ajax请求错误返回status 0和错误error的问题

    上周发现一个jQuery ajax请求错误返回status 0和错误error的问题,responseText是"error",状态码是0而不是200: $.ajax({ type ...

  9. spring全局异常处理 自定义返回数据结构

    在写api接口中,正常返回和异常错误返回我们都希望很清楚的将这些信息清楚的返回给用户,出现异常情况下需要清楚的知道是参数异常还是未知异常,而不是返回一个不正确的数据结构. 所以此处只针对写api接口时 ...

随机推荐

  1. iOS 秒数转换成时间,时,分,秒

    //转换成时分秒 - (NSString *)timeFormatted:(int)totalSeconds{ int seconds = totalSeconds % 60;     int min ...

  2. APP国际化

    1.app本地内容国际化 ①在项目中新建一个New File ---> iOS Resource -> String File ---> 命名为Localizable(之所以命名为L ...

  3. 使用OLE DB读写Excel

    说明: 使用这种技术的好处是无需引用对象,坏处是无法处理类似合并单元格这样的复杂情况 一些更新: 为了使用Office 2010,需要安装Microsoft Access 2010 数据库引擎可再发行 ...

  4. 百度地图API说明

    JZ's Blog的博客对百度地图说明很清晰 http://www.jiazhengblog.com/blog/2011/07/02/289/

  5. Effective Java 03 Enforce the singleton property with a private constructor or an enum type

    Principle When implement the singleton pattern please decorate the INSTANCE field with "static ...

  6. JavaScript Patterns 2.12 Writing API Docs

    Free and open source tools for doc generation: the JSDoc Toolkit (http://code.google.com/p/jsdoc-too ...

  7. MongoDB学习笔记——数据库操作

    使用use数据库名称来创建数据库,如果该数据库已经存在则返回这个数据库 语句格式:use DATABASE_NAME >use mynewdb switched to db mynewdb 使用 ...

  8. 一对一关联查询时使用relation连贯操作查询后,调用getLastSql()方法输出的sql语句

    如题: 一对一关联查询时使用relation连贯操作查询后,调用getLastSql()方法输出的sql语句不是一条关联查询语句. 例如: $list = $db->relation(true) ...

  9. Debian

    一.简介 https://zh.wikipedia.org/wiki/Debian 二.下载 https://www.debian.org/ 三.配置 1)挂载iso镜像 mount /dev/cdr ...

  10. Mac/Linux 定时运行命令行

    想要开机运行的话可以通过 mac 自带的 Automator 将要运行的命令打包成一个app,用后在用户组的“登录时启动”列表里加上那个app. 但是想要定时运行就不能这么做了,要用上一个叫cront ...