【springboot/spring】请求处理源码分析-请求映射的原理

因为springboot请求处理的底层还是采用springMVC那一套原理,所以所有请求还是都要先来到DispatcherServlet被处理,可以从下面的继承层级关系看出来:

在HttpServletBean中没有找到跟doGet、doPost相关的方法,而我们都知道在web中存在HttpServlet的doGet、doPost、doService等方法, 那么我们应该来到HttpServletBean的子类FrameworkServlet中查看是否重写了这些方法:

 

的确存在重写了这些方法(↑HttpServlet表示继承自HttpServlet),而这些doXxx方法都是同一套操作逻辑,都是processRequest(req,resp)方法来实现。

进入processRequest方法查看:

这里发现它调用了doService方法。

doService是一个无实现的抽象方法(说明可能是它的子类实现了doService方法——这个分析思路值得借鉴学习)。

这样下来,一个request映射处理的方法调用思路是这样的:

而调用完doService方法,其实每个request都还需要调用doDispatch方法(最核心的实现方法):

因此,我们可以知道,每个SpringMVC的功能分析都需要从

org.springframework.web.servlet.DispatcherServlet.doDispatch()

这个方法开始。

附完整的doDispatch方法代码:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

        try {
            try {
                ModelAndView mv = null;
                Object dispatchException = null;

                try {
                    processedRequest = this.checkMultipart(request);
                    multipartRequestParsed = processedRequest != request;
                    mappedHandler = this.getHandler(processedRequest);
                    if (mappedHandler == null) {
                        this.noHandlerFound(processedRequest, response);
                        return;
                    }

                    HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                    String method = request.getMethod();
                    boolean isGet = HttpMethod.GET.matches(method);
                    if (isGet || HttpMethod.HEAD.matches(method)) {
                        long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                        if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
                            return;
                        }
                    }

                    if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }

                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }

                    this.applyDefaultViewName(processedRequest, mv);
                    mappedHandler.applyPostHandle(processedRequest, response, mv);
                } catch (Exception var20) {
                    dispatchException = var20;
                } catch (Throwable var21) {
                    dispatchException = new NestedServletException("Handler dispatch failed", var21);
                }

                this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
            } catch (Exception var22) {
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
            } catch (Throwable var23) {
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
            }

        } finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                if (mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            } else if (multipartRequestParsed) {
                this.cleanupMultipart(processedRequest);
            }

        }
}

debug于doDispatch方法的首行,发送某个GET请求,可以看到获取得(mapped)Handler的值:

在此处打断点,并forceInto这一行:

接下来就引出了handlerMappings的概念。handlerMapping是处理器映射的意思。即“/xxx”的请求路径会映射给xxx处理等规则。而且handlerMappings有5个值:

①①RequestMappingHandlerMapping:包含了所有@RequestMapping所有的映射规则和handler的映射规则。而且在this.handlerMappings的mappingRegistry.registry中可以看到我们controller中设置的请求路径都在这里:

因为springboot将RequestMappingHandlerMapping将其注入容器才可以解析到我们注册的controller中的请求(路径):

在这个类中

即:①springboot自动配置了RequestMappingHandlerMapping

②可以看到springboot是自动配置欢迎页的WelcomePageHandlerMapping。(mapping)而且handler也是"forward:index.html"(跳转到欢迎页/首页的路径):

请求进来以后的处理流程为:先尝试所有的HandlerMapping看有无请求信息,如果有就取得handler,其实从刚刚debug在getHandler方法那里也有明显的显示:这一行debug foreInto的时候

这样再次执行getHandler才获取得到mapping为WelcomePageHandlerMapping,因为此时我的请求路径就是/(我浏览器尝试访问首页),而且handler也不为null了,而是上文的分配值。

这样得到handler后才能继续后面的映射处理: 

③也可以自定义HandlerMapping。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值