• 1.1 DispatcherServlet 调度程序


    一、上下文层次结构

             mvc context hierarchy

    二、特殊的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 的ConverterFormatter。

         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的属性:

          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属性显式地启用它们的完整登录

  • 相关阅读:
    2020年MongoDB 企业应用实战 基础 复制集 分片集群
    2020年Redis5.0 从入门到企业应用实战
    2020年Jumpserver1.5.8企业生产部署指南
    python单例与数据库连接池
    python 异常处理
    python 正则
    python 多线程
    python 队列
    python 闭包与装饰器
    程序员面试资源集锦
  • 原文地址:https://www.cnblogs.com/smailjunk/p/11177858.html
Copyright © 2020-2023  润新知