• 深入理解SpringMVC之核心组件、工作原理及相关注解


    GitHub:https://github.com/JDawnF

    目录

    一、核心组件

    1.概述:

    2. MultipartResolver

    MultipartResolver 接口,代码如下:

    3. LocaleResolver

    4. ThemeResolver

    5. HandlerMapping

    6. HandlerAdapter

    7. HandlerExceptionResolver

    8. RequestToViewNameTranslator

    9. ViewResolver

    10. FlashMapManager

    二、SpringMVC工作原理及DispatchServlet源码解析

    三、SpringMVC相关注解

    一、核心组件

    1.概述:

    Spring MVC 一共有九大核心组件,分别是:

    • MultipartResolver

    • LocaleResolver

    • ThemeResolver

    • HandlerMapping

    • HandlerAdapter

    • HandlerExceptionResolver

    • RequestToViewNameTranslator

    • ViewResolver

    • FlashMapManager

    初始化如下: 

    // DispatcherServlet.java
     /** MultipartResolver used by this servlet. */
     @Nullable
     private MultipartResolver multipartResolver;
     ​
     /** LocaleResolver used by this servlet. */
     @Nullable
     private LocaleResolver localeResolver;
     ​
     /** ThemeResolver used by this servlet. */
     @Nullable
     private ThemeResolver themeResolver;
     ​
     /** List of HandlerMappings used by this servlet. */
     @Nullable
     private List<HandlerMapping> handlerMappings;
     ​
     /** List of HandlerAdapters used by this servlet. */
     @Nullable
     private List<HandlerAdapter> handlerAdapters;
     ​
     /** List of HandlerExceptionResolvers used by this servlet. */
     @Nullable
     private List<HandlerExceptionResolver> handlerExceptionResolvers;
     ​
     /** RequestToViewNameTranslator used by this servlet. */
     @Nullable
     private RequestToViewNameTranslator viewNameTranslator;
     ​
     /** FlashMapManager used by this servlet. */
     @Nullable
     private FlashMapManager flashMapManager;
     ​
     /** List of ViewResolvers used by this servlet. */
     @Nullable
     private List<ViewResolver> viewResolvers;
         
     /**
      * This implementation calls {@link #initStrategies}.
      */
     @Override
     protected void onRefresh(ApplicationContext context) {
         initStrategies(context);
     }
         
     /**
      * Initialize the strategy objects that this servlet uses.
      * <p>May be overridden in subclasses in order to initialize further strategy objects.
      */
     protected void initStrategies(ApplicationContext context) {
         // 初始化 MultipartResolver
         initMultipartResolver(context);
         // 初始化 LocaleResolver
         initLocaleResolver(context);
         // 初始化 ThemeResolver
         initThemeResolver(context);
         // 初始化 HandlerMappings
         initHandlerMappings(context);
         // 初始化 HandlerAdapters
         initHandlerAdapters(context);
         // 初始化 HandlerExceptionResolvers 
         initHandlerExceptionResolvers(context);
         // 初始化 RequestToViewNameTranslator
         initRequestToViewNameTranslator(context);
         // 初始化 ViewResolvers
         initViewResolvers(context);
         // 初始化 FlashMapManager
         initFlashMapManager(context);
     }

    2. MultipartResolver

    org.springframework.web.multipart.MultipartResolver ,内容类型( Content-Type )为 multipart/* 的请求的解析器接口。

    例如,文件上传请求,MultipartResolver 会将 HttpServletRequest 封装成 MultipartHttpServletRequest ,这样从 MultipartHttpServletRequest 中获得上传的文件。具体的使用示例,参见 《spring-boot 上传文件 MultiPartFile 获取不到文件问题解决》

    关于内容类型( Content-Type )为 multipart/* ,可以看看 《HTTP 协议之 multipart/form-data 请求分析》 文章。

    MultipartResolver 接口,代码如下:

    // MultipartResolver.java
     public interface MultipartResolver {
         /**
          * 是否为 multipart 请求
          */
         boolean isMultipart(HttpServletRequest request);
     ​
         /**
          * 将 HttpServletRequest 请求封装成 MultipartHttpServletRequest 对象
          */
         MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException;
         /**
          * 清理处理 multipart 产生的资源,例如临时文件
          *
          */
         void cleanupMultipart(MultipartHttpServletRequest request);
     }

    3. LocaleResolver

    org.springframework.web.servlet.LocaleResolver本地化( 国际化 )解析器接口。代码如下:

    // LocaleResolver.java
     public interface LocaleResolver {
         /**
          * 从请求中,解析出要使用的语言。例如,请求头的 "Accept-Language"
          */
         Locale resolveLocale(HttpServletRequest request);
         /**
          * 设置请求所使用的语言
          */
         void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale);
     ​
     }

    具体的使用示例,参见 《SpringMVC学习系列(8) 之 国际化》

    4. ThemeResolver

    org.springframework.web.servlet.ThemeResolver主题解析器接口。代码如下:

    // ThemeResolver.java
     public interface ThemeResolver {
         /**
          * 从请求中,解析出使用的主题。例如,从请求头 User-Agent ,判断使用 PC 端,还是移动端的主题
          */
         String resolveThemeName(HttpServletRequest request);
     ​
         /**
          * 设置请求,所使用的主题。
          */
         void setThemeName(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName);
     }

    具体的使用示例,参见 《如何使用 Spring MVC 主题》

    因为现在的前端,基本和后端做了分离,所以这个功能已经越来越少用了。

    5. HandlerMapping

    org.springframework.web.servlet.HandlerMapping ,处理器匹配接口,根据请求( handler )获得其的处理器( handler)和拦截器们( HandlerInterceptor 数组 )。代码如下:

    // HandlerMapping.java
     public interface HandlerMapping {
         String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";
         String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";
         String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping";
         String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";
         String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";
         String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes";
         /**
          * 获得请求对应的处理器和拦截器们
          */
         @Nullable
         HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
     }
    • 返回的对象类型是 HandlerExecutionChain ,它包含处理器( handler )和拦截器们( HandlerInterceptor 数组 )。简单代码如下:

      // HandlerExecutionChain.java
       /**
        * 处理器
        */
       private final Object handler;
       /**
        * 拦截器数组
        */
       @Nullable
       private HandlerInterceptor[] interceptors;
      • 注意,处理器的类型可能和我们想的不太一样,是个 Object 类型。

    6. HandlerAdapter

    org.springframework.web.servlet.HandlerAdapter ,处理器适配器接口。代码如下:

    // HandlerAdapter.java
     public interface HandlerAdapter {
         /**
          * 是否支持该处理器
          */
         boolean supports(Object handler);
     ​
         /**
          * 执行处理器,返回 ModelAndView 结果
          */
         @Nullable
         ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
         /**
          * 返回请求的最新更新时间。
          *
          * 如果不支持该操作,则返回 -1 即可
          */
         long getLastModified(HttpServletRequest request, Object handler);
     }
    • 因为,处理器 handler 的类型是 Object 类型,需要有一个调用者来实现 handler 是怎么被使用,怎么被执行。而 HandlerAdapter 的用途就在于此。

    7. HandlerExceptionResolver

    org.springframework.web.servlet.HandlerExceptionResolver处理器异常解析器接口,将处理器( handler )执行时发生的异常,解析( 转换 )成对应的 ModelAndView 结果。代码如下:

    // HandlerExceptionResolver.java
     public interface HandlerExceptionResolver {
         /**
          * 解析异常,转换成对应的 ModelAndView 结果
          */
         @Nullable
         ModelAndView resolveException(
                 HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex);
     }

    8. RequestToViewNameTranslator

    org.springframework.web.servlet.RequestToViewNameTranslator ,请求到视图名的转换器接口。代码如下:

    // RequestToViewNameTranslator.java
     public interface RequestToViewNameTranslator {
         /**
          * 根据请求,获得其视图名
          */
         @Nullable
         String getViewName(HttpServletRequest request) throws Exception;
     }

    9. ViewResolver

    org.springframework.web.servlet.ViewResolver实体解析器接口,根据视图名和国际化,获得最终的视图 View 对象。代码如下:

    // ViewResolver.java
     public interface ViewResolver {
         /**
          * 根据视图名和国际化,获得最终的 View 对象
          */
         @Nullable
         View resolveViewName(String viewName, Locale locale) throws Exception;
     }

    ViewResolver 的实现类比较多,例如说,InternalResourceViewResolver 负责解析 JSP 视图,FreeMarkerViewResolver 负责解析 Freemarker 视图。

    10. FlashMapManager

    org.springframework.web.servlet.FlashMapManager ,FlashMap 管理器接口,负责重定向时,保存参数到临时存储中。代码如下:

    // FlashMapManager.java
     public interface FlashMapManager {
         /**
          * 恢复参数,并将恢复过的和超时的参数从保存介质中删除
          */
         @Nullable
         FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response);
         /**
          * 将参数保存起来
          */
         void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response);
     ​
     }

    默认情况下,这个临时存储会是 Session 。也就是说:

    • 重定向前,保存参数到 Seesion 中。

    • 重定向后,从 Session 中获得参数,并移除。

    具体使用示例,参见 《Spring MVC Flash Attribute 的讲解与使用示例》 一文。

    实际场景下,使用的非常少,特别是前后端分离之后。

    二、SpringMVC工作原理及DispatchServlet源码解析

    参照:SpringMVC工作原理及DispatcherServlet源码解析

    三、SpringMVC相关注解

    参照:https://blog.csdn.net/striveb/article/details/90664375

    参照:芋道源码

  • 相关阅读:
    yb课堂 vue里面的状态管理vuex 《四十》
    yb课堂 注册-登陆-个人模块 《三十九》
    MySQL 获取所有表名、所有表结构
    Window版 MySQL可视化工具 Navicat 面安装免激活绿色版
    yb课堂 视频详情页模块开发《三十八》
    yb课堂 首页home开发 《三十七》
    yb课堂 前端项目通用底部选项卡 CommonsFooter 《三十六》
    yb课堂 开发前端项目路由 《三十五》
    yb课堂 基于浏览器和node.js的http客户端Axios 《三十四》
    2020 团体程序设计天梯赛 个人题解 + 反思
  • 原文地址:https://www.cnblogs.com/baichendongyang/p/13235441.html
Copyright © 2020-2023  润新知