一、上下文层次结构
二、特殊的bean类型
目的:处理请求并且返回响应
1.HandlerMapping 映射处理器。一个请求映射到一个handler,进行预处理和后期处理。两个重要的实现RequestMappingHandlerMapping(支持@RequestMapping
)和SimpleUrlHandlerMapping
(为 处理程序维护URI路径模式的显式注册)
2.HandlerAdapter 适配处理器。帮助DispatcherServlet
调用处理器,使一个请求映射到一个handler;
3.HandlerExceptionResovler 异常处理解析器。 处理异常,可以映射异常到handler,错误页面或者其他地方;
4.ViewResolver 视图解析器。把一个handler解析为视图,提交给Response。
5.LocaleResolver 时区解析器。
6.ThemeResolver 主题解析器。
7.MultipartResolver 文件上传解析器。
8.FlashMapManager FlashMap管理。存储和获取FlashMap,在重定向的时候,使属性共享。
三、Web MVC 配置
应用程序可以声明基础的特殊Bean类型,这些类型用来处理请求。DispatcherServlet检查每个特殊bean的WebApplicationContext。如果没有匹配的bean类型,它将返回DispatcherServlet.properties中列出的默认类 型。
四、Servlet 配置
基于xml配置,继承AbstractDispatcherServletInitializer,重写createServletApplicationContext方法,
@Override protected WebApplicationContext createServletApplicationContext() { XmlWebApplicationContext cxt = new XmlWebApplicationContext(); cxt.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml"); return cxt; }
AbstractDispatcherServletInitializer也能增加Filter实例,每个过滤器都根据其具体类型添加一个默认名称,并自动映射到DispatcherServlet。
AbstractDispatcherServletInitializer的isAsyncSupported protected方法提供了一个位置来在DispatcherServlet并且映射所有过滤器到它上,启用异步支持。默认情况下,此标志设置为true。
四、处理请求
DispatcherServlet处理请求方式如下:
1.WebApplicationContext被绑定在请求中,并且能让controller和其他元素使用。默认被绑定在DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE。
2.LocaleResolver 被绑定在请求中
3.ThemeResolver 被绑定在请求中
4.文件请求被包装在MultipartHttpServletRequest中
5.链式执行
6.有model,返回view。没有model,不渲染view。
7.支持返回last-modification-date。如果实现了LastModified,返回最后修改的时间。
8.contextClass 实现ConfigurableWebApplicationContext的类,由这个Servlet实例化并在本地配置。默认情况下,使用XmlWebApplicationContext
9.contextConfigLocation 传递给上下文实例(由contextClass指定)的字符串,以指示可以在何处找到上下文。字符串可能由多个字符串(使用逗号作为分隔符)组成,以支持多个上下文。对于定义了两次bean的多个上 下文位置,最新位置优先。
10.namespace WebApplicationContext的名称空间。默认为servlet-name servlet
11.throwExceptionIfNoHandlerFound 当没有为请求找到处理程序时,是否抛出NoHandlerFoundException。然后可以使用HandlerExceptionResolver捕获异常(例如,通过使用@ExceptionHandler控制器方法),并 像处理其他异常一样处理异常。默认情况下,这被设置为false,在这种情况下DispatcherServlet将响应状态设置为404 (NOT_FOUND),而不会引发异常。注意,如果还配置了缺省servlet处理,未解决的请求总是转发到缺省servlet,并且从来不会引发404。
五、拦截请求
要想实现拦截请求,就要实现HandlerInterceptor,它有三个方法:
preHandle: 应用程序被执行前。
postHandle:应用程序执行后,还没有渲染视图,可以对modelAndView进行操作。
afterCompletion:完成完整的请求后,视图渲染完成后。
perHandle方法会返回一个boolean类型,如果返回true,继续执行下一个拦截器;如果返回false,DispatcherServlet假设这个拦截器已经处理了请求(例如,呈现了一个完整的视图),并且不再执行下一个拦截器和应用程序。
注意:postHandle是不能对 @ResponseBody和@ResponseEntity 注解起作用的,这些方法被编写和提交在 HandlerAdapter 之中并且在postHandle之前。所以如果你想在response中增加一个header,postHandle方法是不行的。针对这个情况,你可以实现ResponseBodyAdvice接口,并将其实现在Controller Advice bean 中,或者直接在RequestMappingHandlerAdapter中配置。
六、异常处理
SimpleMappingExceptionResolver : 异常类名和错误页面之间的映射;
DefaultHandlerExceptionResolver : Spring MVC的异常和 Http状态码的映射;
ResponseStatusExceptionResolver: @ResponseStatus的异常和 Http状态码的映射,Http状态码的值是注解上标记的值;
ExceptionHandlerExceptionResolver:通过调用@Controller或@ControllerAdvice类中的@ExceptionHandler方法来解决异常;
(1)异常链
在Spring配置文件中,可以声明多个HandlerExceptionResolver类,并且执行顺序和配置顺序相同;
异常链返回的规定是:
1、返回一个ModelAndView指向错误的视图;
2、如果异常已经在内部被解决,返回一个空的ModelAndView,;
3、如果异常没有被解决,返回null,以便后面的解析器尝试解决;如果异常在最后仍然存在,就把异常扔到Servlet容器中;
MVC Config 自动声明了内部解析器去处理Spring MVC 的异常。为了支持@ResponseStatus的异常和@ExceptionHandler的方法,可以自定义内部声明的列表或者替换它;
(2)容器中的错误页面
如果任何异常解析器都无法处理异常,导致异常响应给浏览器或者响应的状态码为4xx、5xx。这时Servlet容器能渲染一个默认的html页面,你能在web.xml中配置这个页面的uri,如下代码;
<error-page> <location>/error</location> </error-page>
Servlet API不提供在Java中创建错误页面映射的方法。但是,您可以同时使用WebApplicationInitializer和web.xml。
七、视图处理
ViewResolver
是父接口
AbstractCachingViewResolver :AbstractCachingViewResolver的子类缓存已经解析的视图实例。缓存提高了某些视图技术的性能。您可以通过将cache属性设置为false来关闭缓存。此外,如果必须在运行时刷新某个视图(例如,修改FreeMarker模板时),可以使用removeFromCache(String viewName, Locale loc)方法。
XmlViewResolver:支持XML的配置文件,默认/WEB-INF/views.xml;
ResourceBundleViewResolver:使用bean在ResourceBundle中声明,支持解析每一个视图,使用 [viewname].(class) 作为视图类,使用 [viewname].url 作为视图URL。
UrlBasedViewResolver:该接口在没有显式映射定义的情况下,能直接解析逻辑视图名称到url。如果逻辑名称以一种直接的方式匹配视图资源的名称,而不需要任意映射,那么这是合适的。
InternalResourceViewResolver:UrlBasedViewResolver的便捷子类,它支持内部资源视图(实际上,servlet和jsp)、JstlView和TilesView子类。可以使用setViewClass(..)为这个解析器生成的所有视图指定视图类。
FreeMarkerViewResolver:UrlBasedViewResolver的便捷子类,支持FreeMarkerView和它们的自定义子类;
ContentNegotiatingViewResolver:它根据 请求文件名 或 Accept header 解析视图;
(1)处理
ViewResolver的契约指定它可以返回null来表示找不到视图。然而,对于JSP和InternalResourceViewResolver,判断JSP是否存在的惟一方法是通过RequestDispatcher执行分派。因此,必须始终配置一个InternalResourceViewResolver,使其在视图解析器的整体顺序中位于最后。
(2)重定向redirect
视图名字的前缀表明了重定向操作,UrlBasedViewResolver及其子类承认重定向被需要。redirect:/myapp/some/resource在当前Servlet的上下文中寻找,redirect:https://myhost.com/some/arbitrary/path重定向到一个完整的URL;
(3)转发forward
这将创建一个internalresourceview,它执行RequestDispatcher.forward()。对于InternalResourceViewResolver和InternalResourceView(对于JSP),这个前缀是没有用的,但是如果您使用另一种视图技术,但是仍然希望强制Servlet/JSP引擎处理资源的转发,那么这个前缀是有用的。
(4)内容协商
ContentNegotiatingViewResolver本身并不解析视图,而是委托给其他视图解析器,并选择与客户端请求的表示形式类似的视图。表示可以通过Accept头或查询参数(例如,“/path?format=pdf”)确定。 ContentNegotiatingViewResolver通过将请求媒体类型与每个视图解析器关联的视图支持的媒体类型(也称为内容类型)进行比较,选择适当的视图来处理请求。列表中具有兼容内容类型的第一个视图将表示返回给客户机。如果ViewResolver链不能提供兼容的视图,则会参考通过DefaultViews属性指定的视图列表。后一个选项适用于能够呈现当前的适当表示形式的单例视图。Accept头可以包含通配符(例如text/*),在这种情况下,内容类型为text/xml的视图是兼容的匹配。
八、语言环境
时区TimeZoo :除了获取客户端的语言环境之外,了解其时区通常也很有用。该LocaleContextResolver
接口提供了一个扩展LocaleResolver
,让解析器提供了更丰富的LocaleContext
,其中可能包括时区信息。TimeZone
可以通过RequestContext.getTimeZone()
方法获得 用户。时区信息被Spring注册的对象ConversionService自动转化成任何 Date/Time 的Converter
和Formatter。
header 解析器
环境解析器拦截请求的 accept-language 字段。通常,header字段包含客户端操作系统的语言环境。注意,这个这个解析器不支持 TimeZoo 的信息
Cookie 解析器
环境解析器会拦截请求的 Cookie 字段,看看是否有 Locale 和 Time 被制指定。如果有,使用这些指定的信息。通过使用语言环境解析器的属性,你能指定cookie的名字和最大的年龄。下面是CookieLocaleResolver的例子:
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
<property name="cookieName" value="clientlanguage"/>
<!-- in seconds. If set to -1, the cookie is not persisted (deleted when browser shuts down) -->
<property name="cookieMaxAge" value="100000"/>
</bean>
以下是CookieLocaleResolver的属性:
Property | Default | Description |
---|---|---|
| classname + LOCALE | The name of the cookie |
| Servlet container default | cookie持久化的最长时间。如果是 -1 则表示cookie不能持久化,浏览器关闭cookie消失。 |
| / | 限制了cookie的可见性在站点的特点部分。当指定cookiePath时,cookie仅对该路径及其下面的路径可见。 |
Session 解析器
SessionLocaleResolver允许您从可能与用户请求关联的会话中获得 Local 和 TimeZoo。与CookieLocaleResolver相反,该策略将本地选择的地区设置存储在Servlet容器的HttpSession中。因此,这些设置对于每个会话都是临时的,因此,当每个会话终止时,这些设置就会丢失。
注意,它与外部会话管理机制(如Spring会话项目)没有直接关系。这个SessionLocaleResolver根据当前HttpServletRequest计算和修改相应的HttpSession属性。
Locale 拦截器
您可以通过将LocaleChangeInterceptor添加到HandlerMapping定义之一来启用更改地区。它检测请求中的一个参数并相应地更改区域设置,在dispatcher的应用程序上下文中调用LocaleResolver上的setLocale方法。下面的例子展示了,调用 *.view 的资源就会包含了一个参数siteLanguage。例如,一个URL请求https://www.sf.net/home.view?siteLanguage=nl,就会将站点语言更改为荷兰语。以下是配置
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"> <property name="paramName" value="siteLanguage"/> </bean> <bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver"/> <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="interceptors"> <list> <ref bean="localeChangeInterceptor"/> </list> </property> <property name="mappings"> <value>/**/*.view=someController</value> </property> </bean>
九、多部分解析器
org.springframework.web.multipart 包中的 MultipartResolver 能解析多部分请求包括文件的上传和下载;一个是基于Commons FileUpload实现的,另一个是基于Servlet 3.0 的多部分请求解析的;
想要使用多部分处理,需要在 DispatcherServlet 的Spring 配置中声明一个 MultipartResolver 的bean 。当一个POST请求,它的 content-type = multipart/from-data ,解析器解析内容并且包裹这个当前的 HttpServletRequest 作为 MultipartHttpServletRequest ,把解析的内容作为request的参数。
(1) Apache Commons FileUpload
使用Commons FileUpload 需要配置一个类型为 CommonsMultipartResolver 的bean。需要进入 commons-fileupload 的依赖包。
(2)Servlet 3.0
使用Servlet 3.0 的多部分解析需要通过Servlet容器的设置。这样做:
1.在java中,设置 MultipartConfigElement 在Servlet注册中。
2.在 web.xml 中,增加<multipart-config> 部分在Servlet 的声明中。
十、日志
DEBUG-level :Spring MVC中的调试级日志记录被设计为紧凑、最小且人性化。它着重于反复有用的高价值信息,而不是只在调试特定问题时有用的其他信息。
TRACE-level :跟踪级日志通常遵循与调试相同的原则(例如,也不应该是消防软管),但是可以用于调试任何问题。此外,一些日志消息在跟踪和调试时可能显示不同级别的详细信息。
调试和跟踪日志记录可能会记录敏感信息。这就是为什么请求参数和头在缺省情况下被屏蔽,并且必须通过DispatcherServlet上的enableLoggingRequestDetails属性显式地启用它们的完整登录