Spring 3.x Web MVC
Prepare
REST
-
Url Rewrite Filter
UrlRewriteFilter
Concepts
DispatcherServlet
- Official Reference
- 前端控制分发器
- Context hierarchy in Spring Web MVC
Clean Urls and view-controller
Clean Urls
* `Spring MVC默认无法将/*(不带后缀的,例如.do)的请求送到控制器中。因为/*会包括静态资源,例如/image/a.gif。` * `一般配置不带后缀的,可以单独配置一个路径,该路径下所有的请求都将送到控制器中,例如:/controllers/*。` * `为了将/controllers/*显示成友好的/*形式需借助urlrewritefilter实现。` * `web.xml`
<servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:/spring/applicationContext-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>/controllers/*</url-pattern> </servlet-mapping>
* urlrewrite.xml ``` /images/ /images/$1 /scripts/ /scripts/$1 /styles/** /styles/$1 .....
除了上面的路径,所有路径都派发给控制器
<rule>
<from>/**</from>
<to>/controllers/$1</to>
</rule>
<outbound-rule>
<from>/controllers/**</from>
<to>/**</to>
</outbound-rule>
```
view-controller(From Spring 3)
* `view-controller相当于Struts中的forward action。只用来做页面转发`。 * `applicationContext-mvc.xml`
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/views/" p:suffix=".jsp" /> <mvc:view-controller path="/helloworld" view-name="helloworld"/>
当请求/helloworld时将转发到视图/WEB-INF/views/helloworld.jsp中
* 相当于早期版本中的,起到减少配置量的作用<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/helloworld">indexController</prop> .... </props> </property> </bean> <bean id="indexController" class="org.springframework.web.servlet.mvc.ParameterizableViewController"> <property name="viewName"> <value>index</value> </property>
* 在早期的版本中实现直接的页面跳转,还可以使用
</bean>UrlFilenameViewController
,但无疑还是使用mvc:view-controller
的比较清晰。<bean name="/helloworld" class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />
i18n
配置 ```
```
LocaleChangeInterceptor
LocaleChangeInterceptor用来拦截请求中名称为org.springframework.web.servlet.i18n.LocaleChangeInterceptor.getParamName()的locale参数值,通过LocaleResolver.setLocale方法将具体的locale保存到某处。
LocaleResolver
在DispatcherServlet.render()方法render结果前先调用LocaleResolver.resolveLocale方法获取已经保存的locale,如果没有则获取默认的locale,将DispatcherServlet获取到的locale设置到response中response.setLocale(locale)。
DispatcherServlet持有策略接口LocaleResolve,在初始化此接口时,是从IOC容器中直接按名称DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME "localeResolver"获取具体的实例,如果获取不到,将获取默认的策略对象,目前Spring MVC中的版本是org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver,而该LocaleResovler只支持getLocale方法,而setLocale方法的默认实现是抛出UnsupportedOperationException,所以可以说默认的实现是不支持传参数动态change locle的。
通过以上对源码的分析可以看出,如果要实现传参数动态change locale的功能,需要在IOC容器中配置名称为localeResolverss的LocaleResolver实例。目前Spring MVC提供的可以直接使用的实现有
:org.springframework.web.servlet.i18n.CookieLocaleResolver
org.springframework.web.servlet.i18n.SessionLocaleResolver
org.springframework.web.servlet.i18n.FixedLocaleResolver
org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
可根据需要扩展,建议使用
CookieLocaleResolver
或SessionLocaleResolver
。MessageSource
org.springframework.context.support.ResourceBundleMessageSource and ReloadableResourceBundleMessageSource
see void org.springframework.context.support.ReloadableResourceBundleMessageSource.setCacheSeconds(int cacheSeconds) javadoc
- 配置 ```
或 ```
ResourceBundleMessageSource relies on java.util.ResourceBundle. Reloading a bundle during VM execution is not possible.Consider ReloadableResourceBundleMessageSource for an alternative that is capable of refreshing the underlying bundle files.
- 建议使用
ReloadableResourceBundleMessageSource
,但需详细阅读其javadocTags
jstl <fmt:message key="message.key"/>
spring tags <spring:message code="message.key"/>
使用jstl的fmt:message标签也可以获取messageSource中的国际化消息的原因在于,我们配置的是InternalResourceViewResolver,而InternalResourceViewResolver的默认设置的viewClass为JstlView,当DispatcherServlet.render调用view.render方法时,如果view为JstlView,最终会调用到JstlView.exposeHelpers,在exposeHelpers中调用JstlUtils.exposeLocalizationContext,在exposeLocalizationContext中调用jstl的Config.set方法,将Spring实现的LocalizationContext-SpringLocalizationContext设置到jstl fmt:message标签需要的请求范围变量中。SpringLocalizationContext的getResourceBundle方法返回的ResourceBundle是使用messageSource构建的。
Core Components
Dispatcher Servlet
Handler Mapping
Controller
&
ModelAndView
ViewResolver
&
Views
Interceptors
LocalResolver
Validate
Handler Mapping
SimpleUrlHandlerMapping
ControllerClassNameHandlerMapping
BeanNameUrlHandlerMapping
DefaultAnnotationHandlerMapping
refBased Annotation Spring 3 MVC
Controller
- 实现或继承
Controller,AbstractController
ParameterizableViewController,UrlFilenameViewController
用于直接跳转页面AbstractCommandController,SimpleFormController
在Spring3.0中已经Deprecated.用来封装表单数据等操作。MultiActionController
andInternalPathMethodResovler
,ParameterMethodNameResovler
,PropertiesMethodResovler
DataBinder and PropertyEditor
CustomDateEditor