1、 mvc-convention
The Spring MVC Convention Over Configuration application showcases the
new Convention Over Configuration support introduced in Spring 2.0.
The web application is *very* simplistic, because the intent is
to convey the essence(本质) of the convention over configuration support(配置文档协议支
持)
and nothing else.
<!-- maps request URLs to Controller names 将请求与Controller类名自动匹配 如hello.do自动
查找HelloController实例处理
但是必须要遵守命名规范,它是根据请求路径URI中的路径来匹配Controller,最后一个也就是
文件名,在默认的MethodNameResolver中是
用来匹配Controller的方法,如果没有路径,那么也就根据这个文件名来匹配Controller-->
<bean
class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
<bean id="baseRecipeController" abstract="true">
<property name="recipeManager" ref="recipeManager"/>
</bean>
<!-- Controller names are not important when using the above HandlerMapping
implementation
简单的继承一个虚拟的类,记住这里的继承不是真正意义上的基础,而是在Spring层次上的继
承-->
<bean class="org.springframework.showcase.coverc.web.SwitchBoardController"
parent="baseRecipeController"/>
<bean class="org.springframework.showcase.coverc.web.EditRecipeController"
parent="baseRecipeController">
<property name="commandName" value="recipe"/>
<property name="commandClass"
value="org.springframework.showcase.coverc.domain.Recipe"/>
<property name="formView" value="editRecipe"/>
<property name="successView" value="redirect:switchboard/listRecipes.htm"/>
</bean>
<!-- this bean with the well known name generates view names for us -->
<!-- not strictly required since we just want to accept the defaults-->
<!-- 在Spring2.0中可以不指定View,而由RequestToViewNameTranslator,根据请求来提供View名
称。如想使用
RequestToViewNameTranslator那么请作如下配置,那么就会根据请求来选择提供View,然后在
viewResolver中找页面 -->
<bean id="viewNameTranslator"
class="org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator"/>
<!-- View层解析器,根据传回ModelAndView实例名称来选择View页面 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
流程说明:在web.xml中配置:
<servlet>
<servlet-name>coverc</servlet-name> <servlet-
class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
这个前端控制器,来负责将客户的请求转发给控制对象Controller,针对于转发方案,我们使用
org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping
来映射控制器,将请求与Controller类名自动匹配,如hello.do自动查找HelloController实例处理,但
是必须要遵守命名规范。
如果有映射到的Controller,那么用这个Controller来具体的控制,然后根据在Controller中的
handleRequest中返回的ModelAndView方法的名称来查找View页面,并且将业务层数据来提交给View页面
。
我们使用org.springframework.web.servlet.view.InternalResourceViewResolver这个viewResolver来
根据ModelAndView的名称来选择View 页面,我们可以配置 <property name="prefix"
value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
来确定View页面的地点,prefix是文件夹,suffix是文件后缀。
在Spring2.0中可以不指定View,而由RequestToViewNameTranslator,根据请求来提供View名
称。如想使用RequestToViewNameTranslator那么请作如下配置:
<bean id="viewNameTranslator"
class="org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator"/>
那么就会根据请求来选择提供View,然后在viewResolver中找页面。
属性编辑器:
a) 在BaseCommandController及其子类中的属性编辑器,重写initBinder这个方法中注册:
binder.registerCustomEditor(Long.class, new RecipeEditor());
继承至java.beans.PropertyEditorSupport 将参数转换为指定的对象用setAsText,如果想把
指定的对象转换成String请用getAsText。
b) 还有通过CustomEditorConfigurer这个BeanFactoryPostProcessor来配置PropertyEditor。做如下配
置:
<bean id=”configBean” class=”
org.springframework.beans.factory.config.CustomEditorConfigurer”>
<property name=”customEditors”>
<map>
<entry key=”onlyfun.caterpillar.User”>
<bean id=”userEditor” class=”onlyfun.caterpillar.UserEditor”/>
</entry>
</map>
</property>
</bean>
2、 formtags
1)、如果WebApp中没有配置Handler Mapping,那么它就会使用默认的Handler Mapping ,也就是
BeanNameUrlHandlerMapping,它根据Controller定义中的Bean标签中的name属性的URI,来决定使用哪个
Controller。
2)、ModelAndView中的addObject 通过这里得到存储在modelObject中的对象的简单的类名在加
上Conventions提供的suffix(List)就成为添加在ModelMap中的对象了。
3)、如果在Spring中没有配置RequestToViewNameTranslator,那么系统会给我们一个默认的
DefaultRequestToViewTranslator,根据URI请求,或者映射路径产生。如果我们没有指定viewName,那
么则使用RequestToViewNameTranslator。
ViewName付给当前的ModelAndView,然后根据当前ModelAndView取得View对象,有View对象进行数据存
储,以及根据ViewName进行页面的转发或跳转。
4)、可以在下面配置commandName 和 commandClass, 否则使用默认的,也就是根据返回的对象的实际
的Class信息为commandClass,以默认的“command”为commandName,我们从JSP页面中可以使用这一名
称读取数据。
<bean name="/form.htm"
<property name=”commandName” value=”user”/>
<property name=”commandClass” value=”test.User”/>
class="org.springframework.showcase.formtags.web.FormController">
</bean>
5)、主要流程
DispatcherServlet的doService方法调用doDispatch为处理者处理实际的页面分派任务。
通过servlet的HandlerMapping取得实际的Handler,然后委托给一个servlet预装的HandlerAdapter进行
实际的处理工作,再用这个handlerAdapter取得实际Controller进行实际的操作。
首先调用其handlerRequest方法,其实是调用实际的AbstractController的handlerRequest方法,这里
做了一些session的同步处理,然后调用handleRequestInternal方法进行实际的处理,每种不同的
Controller实现有该方法有不同的实现:
我这里是AbstractFormController,是一种从request中对FormBean能进行自动的组装的Controller,针
对不同的请求isFormSubmission(POST==true)采用不同的策略,GET请求时调用showNewForm方法显示
表单页面;
如果是POST请求那么则进行request参数的FormBean绑定自动装配,进行处理各种验证处理等,然后调用
processFormSubmission方法,如果有任何错误或异常都会调用showForm方法返回的form页面,最后调用
onSubmit进行页面跳转。
6)、总结:
使用Spring的form tag虽然是在使用Spring MVC的最优方案,它能优美的使request的参数与
model模型对象进行绑定,而不像struts那样需要定义额外的formbean类(当然Struts动态bean也可以避
免),所以如果使用Spring MVC务必请使用Spring Form Tag,至于View的逻辑控制请使用JSTL。