Spring Web MVC(一)|前端控制器-DispatcherServlet

Spring MVC Web官方参考文档

1 Spring Web MVC

Spring Web MVC来源于spring-webmvc模块

1.1 DispatcherServlet前端控制器

处于中央Servlet的DispatcherServlet,提供了一种用于请求处理的共享算法,而实际的工作由可配置的委托组件来执行。支持多种工作流程。

DispatcherServlet使用spring的配置来发现它需要的请求映射、视图解析、异常处理、委托组件及其他

以下是在web.xml配置中注册、初试化DispatcherServlet:



    
        org.springframework.web.context.ContextLoaderListener
    

    
        contextConfigLocation
// springmvc配置文件
        /WEB-INF/app-context.xml
    

    
        app
        org.springframework.web.servlet.DispatcherServlet
        
            contextConfigLocation
            
        
        1
    

    
        app
        /app/*
    


1.1.1 应用程序上下文层次结构

Spring Web MVC(一)|前端控制器-DispatcherServlet_第1张图片
Root WebApplicationContext通常包含基础结构bean,在多个DispatcherServlet(或其他Servlet)实例之间共享,每个实例还有其自己的子Servlet WebApplicationContext配置。

在web.xml配置应用程序上下文层次结构



    
        org.springframework.web.context.ContextLoaderListener
    

    
        contextConfigLocation
        
        /WEB-INF/root-context.xml
    

    
        app1
        org.springframework.web.servlet.DispatcherServlet
        
            contextConfigLocation
            
            /WEB-INF/app-context.xml
        
        1
    

    
        app1
        /app1/*
    


如果不需要应用程序上下文层次结构,则应用程序可以仅配置“根”上下文,并将contextConfigLocationServlet参数保留为空。

1.1.2 特殊类型bean-处理请求、渲染响应

在DispatcherServlet中特殊类型bean用于处理请求渲染响应

特殊类型bean指带有内置约束,但可以自定义属性、扩展、替换它们。如:

特殊类型bean 说明
HandlerMapping 请求映射到处理程序以及用于预处理和后处理的拦截器列表 。 映射基于某些标准,其细节因HandlerMapping实现类而异。两个主要HandlerMapping实现类:RequestMappingHandlerMapping (支持带@RequestMapping注释的方法)和SimpleUrlHandlerMapping(维护URI路径模式到处理程序的显式注册)。
HandlerAdapter DispatcherServlet无论如何调用处理程序,都可以使调用映射到请求的处理程序。例如,调用带注解的控制器需要解析注,HandlerAdapter主要目的是保护DispatcherServlet这些细节。
HandlerExceptionResolver 解决异常的策略,将异常映射到处理程序,HTML错误页或其他目标。
ViewResolver 从处理程序返回的基于逻辑的String视图名称解析为View,用于呈现给响应的页面。
LocaleResolver,LocaleContextResolver 解决Locale客户端正在使用的时间区域,以便能够提供国际化的视图。
ThemeResolver 解决Web应用程序可以使用的主题 - 例如,提供个性化布局。
MultipartResolver 在一些多部分解析库的帮助下解析多部分请求(例如,浏览器表单文件上载)的抽象。
FlashMapManager 存储和检索“输入”和“输出” FlashMap,可用于将属性从一个请求传递到另一个请求,通常是通过重定向。

1.1.3 Web MVC配置-DispatcherServlet.properties

应用程序可以声明处理请求所需的特殊类型bean中列出的基础结构bean 。

DispatcherServlet检查 WebApplicationContext中每个特殊类型bean,若没有匹配的bean类型,DispatcherServlet将回退到列出的默认类型DispatcherServlet.properties

1.1.4 Servlet配置-WebApplicationInitializer

在Servlet 3.0+环境中,您可以选择以Java配置Servlet容器作为替代方案或与web.xml文件组合。如:

Java配置:

import org.springframework.web.WebApplicationInitializer;

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) {
        XmlWebApplicationContext appContext = new XmlWebApplicationContext();
        appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");

        ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet(appContext));
        registration.setLoadOnStartup(1);
        registration.addMapping("/");
    }
}

WebApplicationInitializer是Spring MVC提供的接口,可确保检测到您的实现并自动用于初始化任何Servlet 3容器。
AbstractDispatcherServletInitializer抽象类实现了WebApplicationInitializer接口,使DispatcherServlet通过重写方法注册去指定“servlet映射”、“DispatcherServlet配置文件位置” 更容易 。

使用基于Java的Spring配置的应用程序,建议使用此方法:

public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class[] getRootConfigClasses() {
        return null;
    }

    @Override
    protected Class[] getServletConfigClasses() {
        return new Class[] { MyWebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}

使用基于XML的Spring配置,则应直接扩展 AbstractDispatcherServletInitializer

public class MyWebAppInitializer extends AbstractDispatcherServletInitializer {

    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }

    @Override
    protected WebApplicationContext createServletApplicationContext() {
        XmlWebApplicationContext cxt = new XmlWebApplicationContext();
        // spring配置文件
        cxt.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
        return cxt;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}

AbstractDispatcherServletInitializer还提供一种方便的方法来添加Filter 实例并让它们自动映射到DispatcherServlet,如下:

public class MyWebAppInitializer extends AbstractDispatcherServletInitializer {

    // ...

    @Override
    protected Filter[] getServletFilters() {
        return new Filter[] {
            new HiddenHttpMethodFilter(), new CharacterEncodingFilter() };
    }
}

每个过滤器都会根据其具体类型添加一个默认名称,并自动映射到DispatcherServlet。

如果您需要进一步自定义DispatcherServlet自身,则可以覆盖该createDispatcherServlet方法。

1.1.5 Processing处理

DispatcherServlet要求如下:

  • 在WebApplicationContext被搜索并在请求作为在过程控制器和其它元件可以利用一个属性的约束。它默认绑定在DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE密钥下。
  • 语言环境解析器绑定到请求,以允许进程中的元素解析处理请求时使用的语言环境(呈现视图,准备数据等)。如果您不需要区域设置解析,则不需要区域设置解析器。
  • 主题解析器绑定到请求,以允许视图等元素确定要使用的主题。如果您不使用主题,则可以忽略它。
  • 如果指定多部分文件解析程序,则会检查请求的多部分。如果找到多部分,则请求被包装在MultipartHttpServletRequest进程中的其他元素的进一步处理中。
  • 搜索适当的处理程序。如果找到处理程序,则执行与处理程序(预处理程序,后处理程序和控制器)关联的执行链以准备模型或呈现。或者,对于带注释的控制器,可以呈现响应(在其中HandlerAdapter)而不是返回视图。
  • 如果返回模型,则呈现视图。如果没有返回模型(可能是由于预处理器或后处理器拦截请求,可能是出于安全原因),则不会呈现任何视图,因为该请求可能已经完成。

HandlerExceptionResolver特殊类型bean:WebApplicationContext用于解决在请求处理期间抛出的异常。这些异常解析器允许自定义逻辑以解决异常。

DispatcherServlet还支持last-modification-dateServlet API指定的返回 。确定特定请求的最后修改日期的过程很简单: DispatcherServlet查找适当的处理程序映射并测试找到的处理程序是否实现LastModified接口。如果是,则将接口long getLastModified(request)方法的值 LastModified返回给客户端。

可以通过DispatcherServlet将Servlet初始化参数(init-param元素)添加到web.xml文件中的Servlet声明来自定义单个实例。下表列出了支持的参数:

初始化参数 说明
contextClass 实现ConfigurableWebApplicationContext,由此Servlet实例化和本地配置的类。默认情况下,XmlWebApplicationContext使用。
contextConfigLocation 传递给上下文实例(由其指定contextClass)的字符串,用于指示可以在何处找到上下文。该字符串可能包含多个字符串(使用逗号作为分隔符)以支持多个上下文。对于具有两次定义的bean的多个上下文位置,最新位置优先。
namespace WebApplicationContext命名空间。默认为[servlet-name]-servlet。
throwExceptionIfNoHandlerFound NoHandlerFoundException在没有找到请求的处理程序时抛出。然后可以使用HandlerExceptionResolver(例如,通过使用 @ExceptionHandler控制器方法)捕获异常并像其他任何方式一样处理。默认情况下,此设置为false,在这种情况下,DispatcherServlet将响应状态设置为404(NOT_FOUND)而不引发异常。请注意,如果还配置了默认servlet处理,则始终将未解析的请求转发到默认servlet,并且永远不会引发404。

1.1.6 Interception拦截-HandlerInterceptor

所有HandlerMapping实现类都支持处理程序拦截器。HandlerInterceptor拦截器必须从 org.springframework.web.servlet包中实现三种方法,这些方法应该提供足够的灵活性来进行各种预处理和后处理:

  • preHandle(…):在执行实际处理程序之前
  • postHandle(…):处理程序执行后
  • afterCompletion(…):请求完成后

1.1.7 Exceptions异常-HandlerExceptionResolver

若在请求映射期间发生异常或请求处理程序(如 @Controller控制器)抛出异常,则DispatcherServlet委托给特殊类型bean—— HandlerExceptionResolver——链解决异常并提供替代处理,这通常是错误响应。

可用的HandlerExceptionResolver实现类:

实例 说明
SimpleMappingExceptionResolver 异常类名称和错误视图名称之间的映射。用于在浏览器应用程序中呈现错误页面。
DefaultHandlerExceptionResolver 解决Spring MVC引发的异常并将它们映射到HTTP状态代码。
ResponseStatusExceptionResolver 使用@ResponseStatus注释解析异常,并根据注释中的值将它们映射到HTTP状态代码。
ExceptionHandlerExceptionResolver 通过调用或 类中的@ExceptionHandler方法来解决异常。
解析器链

责任链模式

可以通过HandlerExceptionResolver 在Spring配置中声明多个bean并order根据需要设置其属性来形成异常解析程序链。order属性越高,异常解析器定位的越晚。

HandlerExceptionResolver规定它可以返回:

  • ModelAndView指向错误视图
  • ModelAndView如果在解析程序中处理异常,则为空
  • 如果异常仍未解决,则后续解析器尝试。若异常最后还没有处理,则允许冒泡到Servlet容器
容器错误页

如果异常仍然未被任何解析,且HandlerExceptionResolver将其传播或者响应状态设置为错误状态(即4xx,5xx),则Servlet容器可以在HTML中呈现默认错误页面。要自定义容器的默认错误页面,可以声明错误页面映射web.xml。


    /error

上面的示例,当异常冒泡或响应具有错误状态时,Servlet容器会在容器内对配置的URL进行ERROR调度(例如,/error)。然后给DispatcherServlet处理,可能将其映射到@Controller,可以将其实现为使用模型返回错误视图名称或呈现JSON响应,如以下示例所示:

@RestController
public class ErrorController {

    @RequestMapping(path = "/error")
    public Map handle(HttpServletRequest request) {
        Map map = new HashMap();
        map.put("status", request.getAttribute("javax.servlet.error.status_code"));
        map.put("reason", request.getAttribute("javax.servlet.error.message"));
        return map;
    }
}

Servlet API不提供在Java中创建错误页面映射的方法。但是,您可以同时使用WebApplicationInitializer和web.xml

1.1.8 视图解析器-ViewResolver、View接口

Spring MVC定义了一些ViewResolverView接口,使您可以在浏览器中呈现模型,而无需将您与特定的视图技术联系起来。
ViewResolver 提供视图名称和实际视图之间的映射。
View在移交给特定视图技术之前解决数据准备问题。

ViewResolver实现:

视图解析器 说明
AbstractCachingViewResolver AbstractCachingViewResolver他们解析的缓存视图实例的子类。缓存可提高某些视图技术的性能。可以通过将cache属性设置为关闭缓存false。此外,如果必须在运行时刷新某个视图(如修改FreeMarker模板时),则可以用removeFromCache(String viewName, Locale loc)方法。
XmlViewResolver 接受使用与Spring的XML bean工厂相同的DTD以XML编写的配置文件。默认配置文件是 /WEB-INF/views.xml。
ResourceBundleViewResolver 它的实现视图解析器使用bean中的bean定义ResourceBundle,由bundle base name指定。对于应该解析的每个视图,它使用属性的值[viewname].(class)作为视图类,将属性的值[viewname].url用作视图URL。
UrlBasedViewResolver 简单实现的ViewResolver接口会影响逻辑视图名称直接解析为没有显式映射定义的URL。如果您的逻辑名称以直接的方式与视图资源的名称匹配,则这是合适的,而不需要任意映射。
InternalResourceViewResolver 方便的子类UrlBasedViewResolver支持InternalResourceView(实际上,Servlet和JSP)和子类,如JstlView和TilesView。您可以使用指定此解析程序生成的所有视图的视图类setViewClass(…)。
FreeMarkerViewResolver 方便的子类UrlBasedViewResolver支持FreeMarkerView它们的自定义子类
ContentNegotiatingViewResolver 实现ViewResolver基于请求文件名或Accept标头解析视图的接口
处理

可以通过声明多个解析程序bean链接视图解析程序,并在必要时通过设置order属性来指定排序。请记住,order属性越高,视图解析器在链中的位置越晚。

ViewResolver指定它可以返回null以指示无法找到该视图。但是,对于JSP而言,确定JSP InternalResourceViewResolver是否存在的唯一方法是执行调度 RequestDispatcher。因此,您必须在视图解析器链的整体顺序中将InternalResourceViewResolver配置为最后一个视图解析器。

配置ViewResolver视图解析就像在Spring配置中添加bean 一样简单。MVC配置提供了一种专用配置API 视图解析器和用于将逻辑较少视图控制器,其可用于HTML模板呈现而不用控制器逻辑。

重定向

redirect: 视图名称中的特殊前缀,允许执行重定向。UrlBasedViewResolver(和它的子类)识别为是需要重定向的指令。视图名称的其余部分是重定向URL。

请注意,如果使用注解控制器方法**@ResponseStatus**,则RedirectView 注解值优先于设置的响应状态

转发

forward: 前缀表示最终由UrlBasedViewResolver和子类解析的视图名称。这将创建一个InternalResourceView,它执行RequestDispatcher.forward()。因此,对于InternalResourceViewResolver和InternalResourceView(对于JSP),这个前缀是没有用的,但是如果您使用另一种视图技术,但是仍然希望强制Servlet/JSP引擎处理资源的转发,那么这个前缀是有用的。

请注意,您还可以链接多个视图解析器。

内容协商-ContentNegotiatingViewResolver

ContentNegotiatingViewResolver不解析视图本身,而是委托给其他视图解析器并选择类似于客户端请求表示的视图。可以从Accept头部或查询参数(例如,"/path?format=pdf")确定表示。

在ContentNegotiatingViewResolver选择一个适当的View处理由与媒体类型(也称为比较请求的媒体类型的请求 Content-Type被支持)View与每个其相关联ViewResolvers。View列表中具有兼容性的第一个Content-Type将表示返回给客户端。如果ViewResolver链不能提供兼容的视图,DefaultViews则查阅通过该属性指定的视图列表。后一个选项适用于Views可以呈现当前资源的适当表示的单例,而不管逻辑视图名称如何。的Accept 报头可以包括通配符(例如text/*),在这种情况下View,其 Content-Type是text/xml为相容的匹配。

1.1.9 Locale语言环境-LocaleResolver区域解析器

当请求进入时,DispatcherServlet查找区域解析器,如果找到,则尝试使用它来设置区域设置。通过使用RequestContext.getLocale() 方法,您始终可以检索由区域解析器解析的区域设置。

除了自动语言环境解析之外,您还可以将拦截器附加到处理程序映射,用于在特定情况下更改语言环境(例如,基于请求中的参数)。

区域解析器、拦截器在org.springframework.web.servlet.i18n包中定义, 并以正常方式在应用程序上下文中进行配置。

Spring中包含以下选择的语言环境解析器

  • Time Zone:时区
  • Header Resolver:头部解析器
  • Cookie Resolver: cookie解析器
  • Session Resolver :会话解析器
  • Locale Interceptor:区域解析器

1.1.10 Themes主题

应用Spring Web MVC框架主题来设置应用程序的整体外观,从而增强用户体验。主题是静态资源的集合,通常是样式表和图像,它们会影响应用程序的视觉样式。

定义主题

要在Web应用程序中使用主题,必须设置org.springframework.ui.context.ThemeSource接口的实现 。WebApplicationContext 继承了ThemeSource,但其代表职责的专用实现。

默认情况下,委托是一个 org.springframework.ui.context.support.ResourceBundleThemeSource实现,它从类路径的根目录加载属性文件。要使用自定义ThemeSource 实现或配置其基本名称前缀ResourceBundleThemeSource,可以在应用程序上下文中使用保留名称注册bean themeSource。Web应用程序上下文自动检测具有该名称的bean并使用它。

使用ResourceBundleThemeSource时,主题在简单的属性文件中定义。属性文件列出构成主题的资源,如下所示:

styleSheet = /themes/cool/style.css 
background = /themes/cool/img/coolBg.jpg

属性的键是从页面代码引用主题元素的名称。

对于JSP,通常使用spring:theme自定义标记执行此操作,该标记与spring:message标记非常相似。以下JSP片段使用上一示例中定义的主题来自定义外观:

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>

    
        
    
    
        ...
    

解决主题

在DispatcherServlet查找名为ThemeResolver的bean实现类。主题解析器的工作方式与LocaleResolver非常相似。它检测用于特定请求的主题,还可以更改请求的主题。下表描述了Spring提供的主题解析器

说明
FixedThemeResolver 选择使用defaultThemeName属性设置的固定主题。
选择使用defaultThemeName属性设置的固定主题。 主题在用户的HTTP会话中维护。它只需要为每个会话设置一次,但不会在会话之间保留。
CookieThemeResolver 所选主题存储在客户端的cookie中。

Spring还提供了一个ThemeChangeInterceptor允许使用简单的请求参数对每个请求进行主题更改的方法。

1.1.11 多部分解析器-MultipartResolver

MultipartResolverorg.springframework.web.multipart包中解析多部分请求(包括文件上载)的策略。有一个基于Commons FileUpload的实现,另一个基于Servlet 3.0多部分请求解析。

启用多部分解析器,要在DispatcherServletSpring配置中声明一个名为MultipartResolver的bean。在DispatcherServlet检测到它,并将其应用于传入请求。当与内容类型的POST multipart/form-data被接收时,分解器解析该内容和包装了当前HttpServletRequest作为MultipartHttpServletRequest对露出它们作为请求参数提供到解析部件除了访问。

常用多部分解析器

  • Apache Commons FileUpload
  • Servlet 3.0

1.1.13 Logging日志

Spring MVC中的DEBUG级别日志记录旨在实现紧凑,简约和人性化。它侧重于高价值的信息,这些信息一次又一次地有用,而只有在调试特定问题时才有用。

TRACE级日志记录通常遵循与DEBUG相同的原则(例如,也不应该是消防软管),但可以用于调试任何问题。此外,一些日志消息可能在TRACE与DEBUG中显示不同的详细程度。

1.2 Filters过滤器

spring-web模块提供了一些有用的过滤器:

  • Form Data:表格数据
  • Forward Headers:转发标题
  • Shallow ETag:浅tags
  • CORS:跨域请求资源

你可能感兴趣的:(springmvc,Java,Spring,MVC)