别怕下次面试官再问你SpringMVC执行流程了

前言

SSM(Spring+SpringMVC+Mybatis)作为目前主流的JavaEE框架,今天好好聊聊三只神器之一SpringMVC。SpringMVC的名字由两部分组成,Spring 彰显了它的家族身份,而 MVC 则代表它的能力。那么 MVC 究竟是什么呢?
MVC模式:是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。
视图(View) :在 JavaEE 应用程序中,视图(View)可以由 JSP(Java Server Page)担任。在现在前后端分离的模式下,View 已经由前端所取代,而后端负责将处理后的数据以某种格式返回给客户端,比如常用的JSON。
控制器(Controller) :JavaEE 应用中,Controller 可能是一个 Servlet 。在 Spring MVC 中担任控制器角色的是 DispatcherServlet。
模型(Model): Model 则是由一个实体 Bean 来实现,主要对应数据层。比如通过dao层操作数据库返回的数据。

SpringMVC执行原理

Spring MVC 最核心的思想在于 DispatcherServlet 。在现在的开发模式中,我们主要使用的也是 Spring MVC 的这一核心功能。那么 DispatcherServlet 究竟是何方神圣呢?
Spring MVC 内部处理流程如下:
在这里插入图片描述
浏览器发起一个请求(如:http://localhost:8080/student/list), 会经历如下步骤:
1.DispatcherServlet 接收到请求
2.通过 HandlerMapping 找到对应的 handler
3.然后通过 HandlerAdapter 调用 Controller 进行后续业务逻辑处理(3-4)
4.处理完业务逻辑后,Controller 将视图名返回给 HandlerAdapter
5.DispatcherServlet 选择合适的 ViewResolver 生成 View 对象
6.最后 View 渲染并返回响应数据
三个核心组件:

  • Handler
  • HandlerMapping
  • HanderAdapter

Handler 是用来做具体事情的,对应的是 Controller 里面的方法,所有有 @RequestMapping 标注的方法都可以看做为一个 Handler。
HandlerMapping 是用来找到 Handler 的,是请求路径与 Handler 的映射关系。
HandlerAdapter 从名字看,可以知道它是一个适配器。它是用来跟具体的 Handler 配合使用的。可以简单理解为各种电子产品与电源适配器(充电器)的关系。

DispatcherServlet 最核心的方法就是 doDispatch ,doDispatch 主要做了四件事:
根据 request 找到 Handler
根据 Handler 找到对应的 HanderAdapter
用 HanderAdapter 处理 Handler
处理经过以上步骤的结果
别慌,我们调试源码走一遍就明白了:
1.首先来到doDispatch 方法,根据request查找Handler

  @Nullable
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        if (this.handlerMappings != null) {
            Iterator var2 = this.handlerMappings.iterator();

            while(var2.hasNext()) {
                HandlerMapping mapping = (HandlerMapping)var2.next();
                HandlerExecutionChain handler = mapping.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
        }

        return null;
    }

    protected void noHandlerFound(HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (pageNotFoundLogger.isWarnEnabled()) {
            pageNotFoundLogger.warn("No mapping for " + request.getMethod() + " " + getRequestUri(request));
        }

        if (this.throwExceptionIfNoHandlerFound) {
            throw new NoHandlerFoundException(request.getMethod(), getRequestUri(request), (new ServletServerHttpRequest(request)).getHeaders());
        } else {
            response.sendError(404);
        }
    }

若找不到Handler,会给出404的错误返回
2.假如找到Handler,继续根据Handler遍历查找HandlerAdapter

    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
        if (this.handlerAdapters != null) {
            Iterator var2 = this.handlerAdapters.iterator();

            while(var2.hasNext()) {
                HandlerAdapter adapter = (HandlerAdapter)var2.next();
                if (adapter.supports(handler)) {
                    return adapter;
                }
            }
        }

        throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
    }

3.用HanderAdapter处理Handler

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

4.最终将前面的结果统一处理并返回

    private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception {
        boolean errorView = false;
        if (exception != null) {
            if (exception instanceof ModelAndViewDefiningException) {
                this.logger.debug("ModelAndViewDefiningException encountered", exception);
                mv = ((ModelAndViewDefiningException)exception).getModelAndView();
            } else {
                Object handler = mappedHandler != null ? mappedHandler.getHandler() : null;
                mv = this.processHandlerException(request, response, handler, exception);
                errorView = mv != null;
            }
        }

        if (mv != null && !mv.wasCleared()) {
            this.render(mv, request, response);
            if (errorView) {
                WebUtils.clearErrorRequestAttributes(request);
            }
        } else if (this.logger.isTraceEnabled()) {
            this.logger.trace("No view rendering, null ModelAndView returned.");
        }

        if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
            if (mappedHandler != null) {
                mappedHandler.triggerAfterCompletion(request, response, (Exception)null);
            }

        }
    }

至此,SpringMVC的整个流程基本就结束了。抛开原理不谈,SpringMVC提供的注解更为常用,让我们重点处理业务逻辑。

总结

SpringMVC处理流程其实不难,可以与原生的Servlet对比起来,但是相比原生Servlet,SpringMVC提供更为强大的功能。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值