接着上篇文章,大家可能关心的那两个问题
1.controller是怎样进行数据封装的
要说这个问题,我不得不说SimpleFormController了
SimpleFormController是AbstractFormController的具体实现,允许你在配置文件里通过successView和formView属性来配置成功视图(表单成功提交后要转向的页面)和表单视图(显示表单的页面);如果提交不合法(有三种可能:1.validator出错。2.bind错误,也就是说从请求中提取参数封装到command的过程中出现了类型转化错误,比如将一个含字母字符串转换为Integer。3.onBindAndValidate()方法出错),则会重新返回到表单视图;如果提交合法,onSubmit()方法的默认实现会转向成功页面,当然你可以覆写该方法在转向之前填充一些你想返回的信息。
SimpleFormController的工作流与AbstractFormController差不多,唯一的不同是你不必自己去实现showForm()和processFormSubmission()。showForm()这个方法已经被类SimpleFormController实现了并被限定为final,你不可以在继承SimpleFormController的子类里覆写这个类。processFormSubmission()这个方法尽管可以去覆写但由于它几乎可以满足所有的要求,因此一般也不会有人去重写它。
它的处理流程是这样的:
get请求来到时,这样处理:
1) 请求传递给一个controller对象
2) 调用formBackingObject()方法,创建一个command对象的实例。
3) 调用initBinder(),注册需要的类型转换器
4) 调用showForm()方法,返回准备呈现给用户的视图 ,如果“bindOnNewForm”属性设为true,则ServletRequestDataBinder会将初始请求参数填入一个新的表单对象,并且执行onBindOnNewForm()方法。
5) 调用referenceData()方法,准备给用户显示相关的数据。如用户登录需要选择的年度信息
6) 返回formView指定的视图
post请求来到时,这样处理:
1) 如果sessionForm属性没有设定,则调用formBackingObject()方法,创建一个command对象的实例。否则从session中取得表单对象
2) 将请求传来的参数写入command对象,看它的源代码,会发现它是这样来做的:
ServletRequestDataBinder binder = createBinder(request, command);
binder.bind(request);
3)执行onBind()方法,在绑定数据之后,验证数据之前对表单数据进行一些自制的修改动作。
4) 如果设置为要求验证(validateOnBinding属性被设定),则调用validator类进行数据验证
5) 调用onBindAndValidate()方法,该方法允许自定义数据绑定和校验处理
6)执行processFormSubmission()检验 Errors对象中含不含错误,如果含有错误则执行showForm()返回到填写表单页面;否则执行onSubmit()方法,进行提交表单,然后转向成功页面。
2.<spring:kind>的用法
在Spring框架体系下,可以说规约最少,最不受限制的就是表现层技术了。不像Struts,改定了好多的标签,而且有些功能还和标签绑定了。Sping也定义了一些标签,但这些标签只是给使用者提供了一些方便,并不会提供额外的功能或效果。
<sping:bind>的path属性制定了与表单中的那个属性绑定,这样,${status.expression}就代表了那个属性的名称,${status.expression}代表那个属性的值。如果path属性为“XXX.*”则与那个表单的所有属性绑定。
上面的例子表单有两个属性username和password。实际上绑定方式有两种,第一种就像我的上一篇http://javacrazyer.iteye.com/blog/790834文章讲的的那样,第二种如下:
......
<spring:bind path="loginForm">
用户名:<INPUT name="userName" type="text" value="${command.userName}"/><br>
密码:<INPUT name="password" type="password" value="${command.password}"/>
</spring:bind>
这样尽管也行,但在错误信息处理上,针对用户名和密码的报错信息不会像原来那样显示出来了
所以验证我下面要说的话:
使用<sping:bind>标签,在初次进入表单页面时并不会有什么作用,而是当表单提交后,如果有BindException错误时再返回这个页面时,可以把先前的输入显示在input里。
说到错误信息处理,我又要许多要说了,来看看我前一篇文章http://javacrazyer.iteye.com/blog/790834中controller中的
errors.reject("ccc", "用户名或密码有误!");
return new ModelAndView(getFormView(), errors.getModel());
它调用了BindException的reject方法,这样,再调用BindException的getModel()方法,就把错误连同表单等信息一并返回到表单页面用以显示。
reject方法的第一个参数是错误码,如果设定了国际化资源,则显示资源文件中该错误码对应的错误条目,如果没有设定了国际化资源,则显示reject方法的第二个参数。
reject方法的不足之处是在表现层不能区分错误消息属于那个字段,即不能说明是username不对呢还是password不对。解决这种情况可以使用rejectValue方法,这也是更一般使用的方法。rejectValue方法定义如下:
rejectValue(String field, String errorCode, Object[] errorArgs, String defaultMessage)
第一个参数指定表单的域,即username或password,这样就可以分辨到底是那块出了问题;第二个参数和reject方法的第一个参数一样,制定错误码;第三个参选数制定了资源文件中的占位符;第四个参数和和reject方法的第二个参数一样。rejectValue方法还有一个简化的定义
rejectValue(String field, String errorCode, String defaultMessage)
上面是在Controller里使用的方法,使用上述方法后,若果出现BindException错误,返回表单页面时就会显示错误信息,那么如何在页面里显示错误信息呢?
上面/WEB-INF/jsp/login.jsp里由于在controller里使用的是reject方法,所以只能那么显示,如果我们使用rejectValue方法,例如改动LoginController:
errors.rejectValue("userName", "nameErr", null, "用户名错误");
errors.rejectValue("password", "passErr", null, "密码错误");
这样,就可以把页面改为如之前最后的形式
<spring:bind path="command.userName">
名称 <input type="text" name="${status.expression}" value="${status.value}"/>
<font color="red"><c:out value="${status.errorMessage}" /></font><br/>
</spring:bind>
<spring:bind path="command.password">
密码 <input type="password" name="${status.expression}" value="${status.value}"/>
<font color="red"><c:out value="${status.errorMessage}" /></font><br/>
</spring:bind>
这样错误的消息就绑定到相应的字段了。当然也可以不制定某个字段,一股脑都输出
到此,大家还是没看到我是怎样讲解command这个值的,至于为什么非要是command而不是其他值
这是因为setCommandClass这个方法是AbstractController中的一个方法,而这个
方法使用到的一个默认值public static final java.lang.String DEFAULT_COMMAND_NAME = "command";public static final java.lang.String DEFAULT_COMMAND_NAME = "command";
看到了没有,就是叫做command,所以在标签中就敢大胆的用啦
3.最后还有几个小问题
(1)一个常见的错误:
不通过controller直接访问含有spring:bind标签的JSP页面会出现下面的错误:
javax.servlet.ServletException: Neither Errors instance nor plain target object for bean name 'person' available as request attribute
解决办法:
http://spring.jactiongroup.net/viewtopic.php?p=5482
(2)星号(*)的意思
global and all field errors,
## use wildcard (*) in place of the property name
<spring:bind path="company.*">
<c:forEach items="${status.errorMessages}" var="error">
c:out value="${error}"/><br/>
</c:forEach>
</spring:bind>
(3)command的意思
3-1 commandClass
相当于struts中的ActionForm,用来封装V中的数据,方便在C中使用。
3-2 commandName
用来指定JSP中的数据需要绑定到哪个对象。默认为command
比如下面的配置中,commandName就是command
<spring:bind path='command.email'>
<td><input type='text' name='${status.expression}'
value='${status.value}' size='30'
maxlength='100'></td></tr>
</spring:bind>
因为是缺省值,所以它就不需要再在Controller中显示声明
如果在Controller中设置了setCommandName("me");则上面的配置文件需要改为:
<spring:bind path='me.email'>
<td><input type='text' name='${status.expression}'
value='${status.value}' size='30'
maxlength='100'></td></tr>
</spring:bind>
简单吧。
(4)一个要注意的问题(原文链接)
一个普通的<spring.bind>的使用类似于:
<spring:bind path="user.age">
<input type="text" name="age" value="${status.value}">
<font color="red">${status.errorMessage}</font>
</spring:bind>
需要注意的是:<input>的name属性值必须与<spring:bind>的path属性的匹配,否则就绑定不了!
例如下面的代码就绑定不了
<spring:bind path="user.age">
<input type="text" name="theAge" value="${status.value}">
<font color="red">${status.errorMessage}</font>
</spring:bind>
为了避免手误,强烈推荐下列方法来绑定:
<spring:bind path="user.age">
<input type="text" name="${status.expression}" value="${status.value}">
<font color="red">${status.errorMessage}</font>
</spring:bind>
相关推荐
5. **@Controller和@RequestMapping**:讲解这两个关键注解的用途,如何使用它们来定义控制器类和处理方法。 6. **HandlerMapping和HandlerAdapter**:理解这两个组件的作用,它们如何将URL映射到适当的处理器方法...
### 使用Maven构建SpringMVC项目的详细步骤及关键知识点 #### 标题解析与核心知识点说明 - **标题**:“使用maven构建springMVC项目” - **核心知识点**:本篇文章主要围绕如何利用Maven工具来搭建SpringMVC框架...
SpringMVC是Spring框架的重要组成部分,广泛应用于企业级Web开发,因此掌握其工作原理对于提升开发效率和解决技术问题至关重要。 首先,本书会介绍SpringMVC的基本架构,包括Model-View-Controller(MVC)设计模式...
接下来,教程中的核心类与接口部分将介绍SpringMVC中一些关键组件,如Controller、Model、View等,以及这些组件是如何协同工作的。核心流程图会帮助学习者理解一个典型的SpringMVC请求是如何从用户发出,经过处理并...
以下将详细讲解这些技术及其整合过程中的关键知识点。 1. **Spring框架**:Spring是一个开源的应用框架,提供了依赖注入(DI)和面向切面编程(AOP)等核心特性,使得代码更易于测试和管理。在本项目中,Spring作为...
在项目开发过程中,Junit起到了关键的测试保障作用,帮助尽早发现和修复潜在问题。 综上所述,这个项目框架结合了多种技术,实现了完整的Web应用开发流程,包括项目构建、业务逻辑处理、数据访问、视图渲染以及单元...
尚硅谷的SpringMVC课程是为那些希望深入理解这一强大框架的开发者准备的,包括了源码分析和PPT讲解,对于系统学习非常有帮助。 在SpringMVC中,"Model"代表业务数据,"View"负责呈现这些数据,而"Controller"则处理...
以下将从以下几个关键点详细讲解: 1. **DispatcherServlet**:它是SpringMVC的入口,负责接收请求,并根据配置信息(如HandlerMapping)找到合适的处理器(Controller)。 2. **HandlerMapping**:该组件负责将...
在使用Spring MVC搭建项目时,确保拥有正确的依赖是非常关键的。本篇将详细讲解Spring MVC 4.2.1版本的核心概念以及与Log4j2日志库的结合使用。 1. **Spring MVC 框架核心组件** - **DispatcherServlet**:作为...
通过“SpringMVC实战”高清视频教程,学习者将能全面了解和掌握SpringMVC的各个关键特性,并能在实际项目中灵活运用。课程中可能涵盖以上知识点的详细讲解,包括配置、使用示例以及常见问题的解决方法。观看此教程,...
《看透SpringMVC源代码分析与实践》一书由韩路彪撰写,专注于解析SpringMVC这一核心的Java Web...通过阅读《看透SpringMVC源代码分析与实践》,开发者可以更深入地理解SpringMVC的精髓,提升开发效率和问题解决能力。
使用SQL脚本可以快速创建和配置所需的表结构,包括用户信息、菜品管理、订单处理等关键业务数据。开发者需要根据实际情况对这些脚本进行修改,以适应特定的业务需求。 "client_home"和"client_admin"分别代表了用户...
以下将详细讲解SpringMVC的核心概念、架构和主要组件。 1. **DispatcherServlet**:SpringMVC的核心组件,作为前端控制器,接收所有HTTP请求,并根据配置的映射规则转发到相应的处理器。 2. **Model-View-...
在本文中,我们将深入探讨SpringMVC框架中的数据绑定,这是Spring MVC开发中不可或缺的一部分,...在实际开发中,还需要了解如何配置SpringMVC,以及如何处理异常和国际化等问题,这些都是构建健壮Web应用的关键环节。
在mybatis第二天课堂笔记.docx中,可能会深入讲解动态SQL、结果映射、缓存机制、事务管理等高级特性,这些都是MyBatis提高开发效率和优化性能的关键。此外,还可能涉及MyBatis与Spring的整合,利用Spring的依赖注入...
本文主要讲解了如何将阿里巴巴的Dubbo、Zookeeper和SpringMVC整合使用,以实现高效的服务治理和调用。 首先,Dubbo是一个高性能、轻量级的Java分布式服务框架,它主要解决了在微服务架构中服务间的通信问题。在...
本文将详细讲解如何利用Spring MVC结合开源库实现Excel和PDF的生成。 首先,我们要引入两个关键的库:Apache POI用于生成Excel,iText或Flying Saucer用于生成PDF。Apache POI是一个流行的API,它允许Java程序员...
这份手册涵盖了Spring框架、SpringMVC模块以及MyBatis持久层框架的基础知识,包括环境搭建、架构设计、数据传递以及逆向工程等关键点。 在Spring MVC部分,首先会讲解到的是单例与多例的概念。在Java中,单例模式...
本篇将基于一个简单的示例,来讲解如何使用Spring MVC实现文件上传功能。 #### 二、环境配置与依赖 1. **项目构建**:确保项目是基于Spring MVC框架构建的。 2. **依赖添加**:在项目的pom.xml文件中添加以下依赖...
在Spring MVC框架中,数据验证是一项关键功能,用于确保用户提交的数据符合预设的规则和格式,从而保证系统的稳定性和数据的准确性。本教程将详细讲解如何在Spring MVC中实现注册用户时的数据验证实例。 首先,我们...