Spring Web MVC(原理与代码详解)

2022-09-06 09:38:16

文章目录


前言

Spring Web MVC 是基于Servlet API构建的Web框架,初始Spring框架就包含了该框架。

与其他许多web框架一样,Spring MVC的设计是围绕前置控制器模式其中心是Servlet,DispatcherServlet 为请求处理提供了一个共享算法,而实际工作是由可配置的代理组件执行的,这种模型灵活且执行多种工作流。

DispatcherServlet和任何Servlet一样,需要使用Java配置或web.xml配置,根据Servlet规范进行声明和映射。
反过来说DispatcherServlet使用Spring配置去发现所需要的代理组件,如:请求映射、试图解析、异常处理等。

配置示例

基于Java配置

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) {

        // Load Spring web application configuration
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(AppConfig.class);

        // Create and register the DispatcherServlet
        DispatcherServlet servlet = new DispatcherServlet(context);
        ServletRegistration.Dynamic registration = servletContext.addServlet("app", servlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/app/*");
    }
}

基于 Web.xml配置

<web-app><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><context-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/app-context.xml</param-value></context-param><servlet><servlet-name>app</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value></param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>app</servlet-name><url-pattern>/app/*</url-pattern>
    </servlet-mapping>
</web-app>

这两个配置是一样的意思。

DispatcherServlet主要组件

doService方法

  1. 请求头设置WEB_APPLICATION_CONTEXT(Web应用上下文)
  2. 请求头设置LOCALE_RESOLVER(本地化解析器)
  3. 请求头设置THEME_RESOLVER(主题解析器)
  4. 请求头设置THEME_SOURCE(主题资源)
  5. 请求头设置OUTPUT_FLASH_MAP(输出FLASH_MAP)
  6. 请求头设置FLASH_MAP_MANAGER(FLASH_MAP管理)

doDispatch方法

  1. 判断当前请求是否是MultiPart请求,如果是则通过MultipartResolver将HttpServletRequest解析为MultipartHttpServletRequest。
  2. 通过List<HandleMapping>,来获取到HandlerExecutionChain,当前对象包含handler(具体执行的对象)和interceptors(在执行时候的拦截器)。
  3. 通过List<HandlerAdapter>对象,是否支持HandlerExecutionChain对象中的handler的适配,支持则返回HandlerAdapter。
  4. HandlerExecutionChain执行拦截器前置处理器方法applyPostHandle()。
  5. 通过HandlerAdapter中的handle执行HandlerExecutionChain中的handle的具体执行。返回ModeAndView(试图)。
  6. 如果模型和试图不为空,判断是否有默认模型和试图。
  7. HandlerExecutionChain执行拦截器后置处理器方法applyPostHandle()。
  8. 执行Dispatch结果方法processDispatchResult,来完成视图的装配工作。

MultipartResolver(多文件解析器)

如果请求需要上传文件,就需要配置MultipartResolver,来完成将HttpServletRequest转换为MultipartHttpServletRequest。

StandardServletMultipartResolver

  1. 判断请求头Content-Type参数值是否已multipart/来判断是否是多文段请求。
  2. 通过request.getParts(),来解析每一段的内容,如果是文件添加到MultipartFiles中。
  3. 如果是参数则添加到multipartParameterNames。

CommonsMultipartResolver

  1. 是借助了Apache Commons FileUpload 组件完成对应文件解析
  2. 提供了更多的功能:如限制总文件上传大小,限制每个文件上传大小,设置编码等。
  3. 只支持POST以及求头Content-Type参数值是否存在multipart/来判断是否是多文段请求。
  4. 通过request.getParts(),来解析每一段的内容,如果是文件添加到MultipartFiles中。
  5. 如果是参数则添加到multipartParameterNames。

LocaleResolver(本地化解析器)

根据用户当前使用的区域设置以及可能的时区,以便能够提供国际化试图。

AbstractLocaleContextResolver(时间区域)

通过使用RequestContext获取用户的时区。getTimeZone()方法。来获得本地化Locale。

实现分别有:
FixedLocaleResolver:只能返回默认设置的Locale和TimeZone。
SessionLocaleResolver:将TimeZone和Locale保存到Session中。

AcceptHeaderLocaleResolver(请求头解析)

通过请求头accept-language来获取到对应的,不支持时区解析。

CookieLocaleResolver(Cookie解析器)

解析客户端上Cookie,是否设置了Locale或Timezone。如果设置了则使用指定详细信息。

Locale Interceptor(本地化拦截器)

可以通过将LocaleChangeInterceptor添加到HandlerMapping去修改本地化,在检测到请求头参数并修改对应的Locale值。

默认使用:AcceptHeaderLocaleResolver

Themes(主题)

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

主体必须和主题资源结合在一起使用

ResourceBundleThemeSource设置主题资源
styleSheet=/themes/cool/style.css
background=/themes/cool/img/coolBg.jpg

JSP页面使用示例,读取key即可。

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%><html><head><link rel="stylesheet" href="<spring:theme code='styleSheet'/>" type="text/css"/></head><body style="background=<spring:theme code='background'/>">...</body></html>

FixedThemeResolver(固定主题解析)

只能设置默认主题,提供默认主题

SessionThemeResolver(会话主题解析)

主题在用户的HTTP会话中维护,它只需要为每个会话设置一次,但不会在会话之间持久化。

CookieThemeResolver(Cookie主题解析)

主题存储在客户端的Cookie中。

ThemeChangeInterceptor(主题更改拦截器)

通过拦截器允许通过一个简单的请求参数在每个请求上更改主题。

默认使用:FixedThemeResolver

HandlerMapping(处理器映射)

将请求映射到处理程序以及用户预处理和后处理的拦截器列表。映射基于一些标准,这个标准的细节由HandlerMapping具体实现而异。

AbstractHandlerMapping

  1. 通过getHandlerInternal获取对象Handler。
  2. 如果Handler是字符串,成Bean工厂获取到对象。
  3. 通过getHandlerExecutionChain获得Handel执行链对象HandlerExecutionChain
  4. 如果是Cors的则返回Cors校验的执行链。

AbstractUrlHandlerMapping

  1. 同配置的URL和对象,来获取对象的。

AbstractHandlerMethodMapping

  1. 根据注解RequestMapping或是Controller生成对应的MappingRegistry。
  2. 从MappingRegistry获取对应的Handler

RouterFunctionMapping

默认使用
BeanNameUrlHandlerMapping
RequestMappingHandlerMapping
RouterFunctionMapping

HandlerAdapter(处理器适配器)

  1. 判断当前HandlerAdapter(处理器适配器)是否执行当前的Handler(处理器)
  2. 如果支持值采用当前适配器,去执行具体的请求。
  3. 并返回ModeAndView。其值可为空。

HttpRequestHandlerAdapt

  1. 支持Handler为HttpRequestHandler的适配器
  2. 具体执行由HttpRequestHandler中handleRequest方法执行

SimpleServletHandlerAdapt

  1. 支持Handler为Servlet的适配器
  2. 具体执行由Servlet中service方法执行

HandlerFunctionAdapt

  1. 支持Handler为HandlerFunction的适配器
  2. 具体执行由HandlerFunction中handle方法执行

CompositeHandlerAdapt

  1. 通过代理HandlerAdapter列表,通过具体的HandlerAdapter来判断是否执行
  2. 通过代理执行具体的方法。

RequestMappingHandlerAdapt

  1. 支持Handler为HandlerMethod的适配器
  2. 具体执行由HandlerMethod中ServletInvocableHandlerMethod对象。
  3. 通过ServletInvocableHandlerMethod中的invokeAndHandle执行具体的方法。
  4. 一般我们写的请求都是属于这一类。

SimpleControllerHandlerAdapt

  1. 支持Handler为Controller的适配器
  2. 具体执行由Controller中handleRequest方法执行

默认使用
HttpRequestHandlerAdapter
SimpleControllerHandlerAdapter
RequestMappingHandlerAdapter
HandlerFunctionAdapter

HandlerExceptionResolver(处理器异常解析器)

HandlerExceptionResolverComposite

  1. 通过代理对象执行具体的异常解析

CompositeHandlerExceptionResolver

  1. 通过工厂方法获得所有已创建Bean的HandlerExceptionResolver对象。
  2. 如果为空则创建:DefaultErrorAttributes和DefaultHandlerExceptionResolver。
  3. 通过代理执行具体的异常解析。

DefaultErrorAttributes

  1. 通过将异常数据写入到请求参数中。

SimpleMappingExceptionResolver

  1. 可以设置排除异常,发生这个异常不返回信息。
  2. 配置异常类的属性文件
  3. 如果是在对应的属性异常类中,则返回对应的试图名称。

ExceptionHandlerExceptionResolver

  1. 根据异常类信息,判断是否有指定异常的方法。如果有则根据异常指定方法返回。
  2. 如果没有则返回空。

DefaultHandlerExceptionResolver

  1. 根据异常类名,返回默认的异常ModeAndView。
  2. 如果异常类不在指定的范围,则返回空。

ResponseStatusExceptionResolver

  1. 根据如果响应异常状态不为空(只配置了的状态)来返回指定的ModeAndView信息。
  2. 如果为异常类,则返回ModeAndView(对应异常信息)。
  3. 都不是返回null。

默认使用
ExceptionHandlerExceptionResolver
ResponseStatusExceptionResolver
DefaultHandlerExceptionResolver

RequestToViewNameTranslator(请求视图名称转换)

  1. 根据传入的名称,返回真正的试图名称。

DefaultRequestToViewNameTranslator

  1. 设置视图的前缀后缀
  2. 根据配置规范进行转换,在拼接上前缀和后缀。

默认值DefaultRequestToViewNameTranslator

FlashMapManager(FlashMap管理)

SessionFlashMapManager

默认启用:SessionFlashMapManager

ViewResolver(试图解析)

根据viewName(视图名称)和locale(本地化)来获取对应的View。

SessionFlashMapManager

  1. 通过代理对应的ViewResolver对象,来执行具体的试图解析。

BeanNameViewResolver

  1. 通过判断viewName(视图名称)是否一个Bean,且Bean的类型为View.class
  2. 如果是返回对应View,否则返回null。

ContentNegotiatingViewResolver

ResourceBundleViewResolver

XmlViewResolver

UrlBasedViewResolver

TilesViewResolver

ScriptTemplateViewResolver

InternalResourceViewResolver

XsltViewResolver

MustacheViewResolver

GroovyMarkupViewResolver

FreeMarkerViewResolver

默认启用:InternalResourceViewResolver

  • 作者:swg321321
  • 原文链接:https://blog.csdn.net/swg321321/article/details/126108178
    更新时间:2022-09-06 09:38:16