代码改变世界

11月19日spring mvc的表单处理的相关知识

2006-11-21 20:36  java ee spring  阅读(176)  评论(0编辑  收藏  举报

1.查看帮助文档,了解spring中提供了哪些自定义标签以及这些标签的用途与用法。通过实际的例子演示了如何使用<spring:message>来显示国际化的文本信息,如何使用<spring:bind>标签来显示对象及对象的属性信息。

2.<spring:bind>只能绑请求域中的对象信息,<spring:bind>生成status属性变量的类型为org.springframework.web.servlet.support.BindStatus,status属性变量只能在<spring:bind>标签对之间使用。查看org.springframework.web.servlet.tags.BindTag、org.springframework.web.servlet.support.BindStatus、org.springframework.web.servlet.support.RequestContext、org.springframework.validation.BindException的源文件,可以看到程序的处理路线为:BindTag创建BindStatus对象,BindStatus对象在构造方法中调用requestContext.getErrors(beanName, false)方法,getErrors方法调用getModelObject(BindException.ERROR_KEY_PREFIX + name)方法,getModelObject方法调用request.getAttribute(modelName),其中modelName就是BindException.ERROR_KEY_PREFIX + name的值,BindException.ERROR_KEY_PREFIX就是BindException的完整类名。通过分析这些源代码,得到一个结论:<spring:bind>标签实际上是在请求域取errors对象,errors对象的类型为org.springframework.validation.BindException,然后从errors对象中检索与path指定的对象或属性相关的错误,并且从errors对象中还可以检索出某个字段的值,即error对象中也包含了字段的信息。

3.讲解了SimpleFormController的作用:
显示表单
(1).handleRequest(HttpServletRequest request, HttpServletResponse response)
(2).handleRequestInternal(HttpServletRequest request,HttpServletResponse response)
(3).formBackingObject()
(4).initBinder()
 可选:onBindOnNewForm(HttpServletRequest, Object, BindException)
(5).showForm()
(6).referenceData()

处理标单
(1).handleRequest(HttpServletRequest request, HttpServletResponse response)
(2).handleRequestInternal(HttpServletRequest request,HttpServletResponse response)
(3).formBackingObject()
(4).onBind(HttpServletRequest, Object, Errors)
(5).绑定数据
(6).onBindAndValidate()
(7).processFormSubmission()
校验无错
(8).onSubmit
(9).doSubmitAction
校验有错
(8).showForm
产生错误的一个小技巧:在Command对象中设计一个int类型的属性,在表单提交时,故意提交一个字符串,这样就会发生类型转换错误,回到FormView视图。

4.通过下面的程序,可以显示出错误信息的属性key与错误信息的对象类型,还可以显示出Command对象的属性key与Command对象的类型。
logon.jsp:
    <FORM action="logon.html" method="POST">
     <spring:bind path="wangzy.username">
     <INPUT type="text" name="username" value="${status.value}">${status.errorMessage}
     </spring:bind>
       <INPUT type="password" name="password">
        <INPUT type="submit" name="logon" value="<spring:message code="hello.title" arguments="wzy"/>">
    </FORM>
       <% Enumeration e = request.getAttributeNames();
     while(e.hasMoreElements())
     {
      String attributeName = (String)e.nextElement();
      out.println(attributeName + ":" +
       request.getAttribute(attributeName).getClass().getName() + "<br>");
     }
    %>
将logon.jsp作为一个SimpleFormController的FormView,logon.html映射到这个SimpleFormController,第一次直接访问logon.html时,显示logon.jsp页面的内容,结果如下:
javax.servlet.forward.request_uri:java.lang.String
javax.servlet.forward.context_path:java.lang.String
javax.servlet.forward.servlet_path:java.lang.String
javax.servlet.forward.query_string:java.lang.String
wangzy:cn.itcast.mvc.UserCommand   !!!!!
org.springframework.web.servlet.DispatcherServlet.THEME:org.springframework.web.servlet.theme.FixedThemeResolver
org.springframework.web.servlet.DispatcherServlet.CONTEXT:org.springframework.web.context.support.XmlWebApplicationContext
org.springframework.validation.BindException.wangzy:org.springframework.validation.BindException  !!!!!!
org.springframework.web.servlet.DispatcherServlet.LOCALE:org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

从整个程序的执行结果中可以发现,无论失败后的form视图,还是成功视图,其中的request域中都包含有command对象和错误对象,Command对象的默认key为"command",但可以通过setCommandName方法修改。只要用了SimpleFormController,即使是第一次显示form视图,其中的request域中也包含了command对象和错误对象,只是他们的值都是初始值和空,这主要是为了让<spring:bind>能够有对象可绑,而不会出现错误。应该在下次有机会时,让学员们看看相关的源代码,以了解command对象和错误对象是如何绑定到request域中的。提示:在AbstractFormController或SimpleFormController源文件中查找request.setAttribute应该是最快的方式,我找了一下,好象没这么容易,看看是哪个工具类完成的,然后在工具类中找setAttribute。怪:我在spring源目录中搜索BindException这个词,怎么只搜索到包含有这个词文件名,而不在.java文件内容中搜索?

以前的对比实验结论:对于实现AbstractCommandController的Controller,它不会在request域中自动保存command对象和错误对象。

最后问了一个问题:在SimpleFormController的构造方法中编程设置FormView,在配置文件中也设置FormView属性,问哪个属性设置将起作用,结果回答正确的学员很少,他们就没想到setter方法肯定后于构造方法调用这个道理上来。

小知识:在什么情况下要将Command对象保存在Session域中,这可以通过setSessionForm方法来完成。