Export to GitHub

bounding - SpringMVC3.wiki


Spring 3.x Web MVC

Prepare

REST

Concepts

DispatcherServlet

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
    • 可根据需要扩展,建议使用CookieLocaleResolverSessionLocaleResolver

      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,但需详细阅读其javadoc

      Tags

  • 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 ref Based Annotation Spring 3 MVC

Controller

  • 实现或继承Controller,AbstractController
  • ParameterizableViewController,UrlFilenameViewController用于直接跳转页面
  • AbstractCommandController,SimpleFormController在Spring3.0中已经Deprecated.用来封装表单数据等操作。
  • MultiActionController and InternalPathMethodResovler,ParameterMethodNameResovler,PropertiesMethodResovler

DataBinder and PropertyEditor

  • CustomDateEditor