SpringMVC 第三章 - DispatcherServlet的逻辑处理

简介: 这部分应该是SpringMVC的核心,也是我们在平常使用的时候经常会被问到的一个问题,在大学刚接触SpringMVC的时候,经常会看到下面这样的流转图 简单的说一下,就是每一个请求过来的时候,都是由DispatcherServlet进行转发,那么它的第一步就是用过映射处理器(BeanNameUrlHandlerMapping)找到对应的实体类(Controller类),然后再拿这个实体类和每个Adapter进行适配。
这部分应该是SpringMVC的核心,也是我们在平常使用的时候经常会被问到的一个问题,在大学刚接触SpringMVC的时候,经常会看到下面这样的流转图

image

   简单的说一下,就是每一个请求过来的时候,都是由DispatcherServlet进行转发,那么它的第一步就是用过映射处理器(BeanNameUrlHandlerMapping)找到对应的实体类(Controller类),然后再拿这个实体类和每个Adapter进行适配。那么最最重要的,需要理解的,也是就是上一章节说到两个模块:映射处理器和适配器。

  由于 DispatcherServlet 继承 FrameworkServlet, Servlet的默认实现doGet,doPost的实现都指向了DispatcherServlet的**doService**方法,在进行doService方法之前,使用了ThreadLocal保存了当前线程的属性

最重要的两个方法:

  1. 由handlerMapping获取到对应的handler
  2. 找到合适的handlerAdapter,然后调用handler方法

/**
 *  根据request信息寻找对应的Handler
 *  private List<HandlerMapping> handlerMappings  是初始化的时候设置 -- initHandlerMappings(context)
 */
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        for (HandlerMapping hm : this.handlerMappings) {
            // 封装处理
            HandlerExecutionChain handler = hm.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
        return null;
 }


/**
  *      根据URL找到匹配的Controller并且返回,如果当前没有找到对应的Controller处理器,那么程序会尝试查找配置中的默认处理器
  * 当然,当查找的controller为String类型的时,那就意味着返回的是配置的bean名称,需要根据bean名称查找对应的Bean,最后还要
  * 通过getHandlerExecutionChain()方法对返回的Handler进行封装,以保证满足返回类型的匹配
  */
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
      // 根据request获取对应的handler
      Object handler = getHandlerInternal(request);

      if (handler == null) {
      // 如果没有对应的request的handler则使用默认的handler
      handler = getDefaultHandler();
      }

     if (handler == null) {
      return null;
      }

     if (handler instanceof String) {
      String handlerName = (String) handler;
      handler = getApplicationContext().getBean(handlerName);
      }

      // 加入拦截器到执行链
      HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
      if (CorsUtils.isCorsRequest(request)) {
        CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
        CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
        CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
        executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
    }
    
    return executionChain;
}

根据Request查找对应的Handler
(1) 截取用于匹配的url有效路径
(2) 根据路径寻找Handler

protected Object getHandlerInternal(HttpServletRequest request) throws Exception {

        // 截取用于匹配规则的URL有效路径
        String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);

        // 根据路径寻找Handler
        Object handler = lookupHandler(lookupPath, request);
        if (handler == null) {
            Object rawHandler = null;
            if ("/".equals(lookupPath)) {
                // 如果请求的路径仅仅是"/" 那么使用RootHandler处理
                rawHandler = getRootHandler();
            }
            if (rawHandler == null) {
                // 如果无法找到handler则使用默认handler
                rawHandler = getDefaultHandler();
            }
            if (rawHandler != null) {
                if (rawHandler instanceof String) {
                    // 根据beanName获取对应的Bean
                    String handlerName = (String) rawHandler;
                    rawHandler = getApplicationContext().getBean(handlerName);
                }
                // 模板方法
                validateHandler(rawHandler, request);
                handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);
            }
        }
        return handler;
    }

将Handler封装成HandlerExecutionChain类型,并且加入两个拦截器,这是一个很优秀的设计模式,后面会专门说到

protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern,
                                      String pathWithinMapping, Map<String, String> uriTemplateVariables) {

    HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler);
    
    // 加入拦截器
    chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping));
    
    // 加入拦截器
    if (!CollectionUtils.isEmpty(uriTemplateVariables)) {
       chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables));
    }
    return chain;
}
 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
 这段代码其实就是将配置的拦截器加入到拦截链中
  

   ----
  
目录
相关文章
|
1月前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
33 1
|
1月前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
31 1
|
1月前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
25 0
SpringMVC源码解析DispatcherServlet#doDispatch方法流程(下)
SpringMVC源码解析DispatcherServlet#doDispatch方法流程(下)
314 0
SpringMVC源码解析DispatcherServlet#doDispatch方法流程(下)
|
设计模式 开发框架 前端开发
SpringMVC源码解析DispatcherServlet#doDispatch方法流程(上)
SpringMVC源码解析DispatcherServlet#doDispatch方法流程(上)
263 0
SpringMVC源码解析DispatcherServlet#doDispatch方法流程(上)
|
Java Spring
SpringMVC解析4-DispatcherServlet逻辑脉络
HttpServlet提供了不同的服务方法,它们是doDelete(),doGet(),doOptions(),doPost(),doPut(),和doTrace(),它会根据不同的请求形式将程序引导至对应的函数进行处理。
690 0
|
缓存 Java Spring
SpringMVC解析5-DispatcherServlet逻辑细节
MultipartContent类型的request处理 对于请求的处理,spring首先考虑的是对于Multipart的处理,如果是MultipartContent类型的request,则转换request为MultipartHttpServletRequest类型的request.
737 0
|
7月前
|
设计模式 前端开发 JavaScript
Spring MVC(一)【什么是Spring MVC】
Spring MVC(一)【什么是Spring MVC】
|
6月前
|
设计模式 前端开发 Java
【Spring MVC】快速学习使用Spring MVC的注解及三层架构
【Spring MVC】快速学习使用Spring MVC的注解及三层架构
89 1
|
6月前
|
前端开发 Java 应用服务中间件
Spring框架第六章(SpringMVC概括及基于JDK21与Tomcat10创建SpringMVC程序)
Spring框架第六章(SpringMVC概括及基于JDK21与Tomcat10创建SpringMVC程序)