SpringMVC的工作原理及其执行流程

文章目录

前言

一、Spring Mvc的核心组件

二、Spring Mvc 的执行流程。

        如图所示:

1. 请求入口:用户请求到达 DispatcherServlet

2. 查找处理器:HandlerMapping 定位处理器

3. 适配处理器:HandlerAdapter 统一调用接口

4. 拦截器前置处理:preHandle ()

5. 执行处理器:调用 Controller 方法

6. 拦截器后置处理:postHandle ()

7. 解析视图:ViewResolver 解析视图名

8. 渲染视图:填充模型数据到视图

9. 拦截器完成处理:afterCompletion ()

10. 响应客户端

核心设计模式与总结


前言

    首先,MVC模式 是模型(Model)、视图(View)、控制器(Controller)的简写,其核心思想是通过将请求处理控制、业务逻辑、数据封装、数据显示等流程节点分离的思想来组织代码。如图所示:


   所以,MVC 是一种设计模式,而Spring MVC 是一款基于MVC设计模式思想实现的的 MVC 框架,属于Spring技术栈的一部分。Spring MVC 可以帮助我们进行更简洁的 Web 层的开发,并且它天生与 Spring框架集成,更利于架构的设计与搭建。

一、Spring Mvc的核心组件

1:DispatcherServlet :核心处理器,负责统一接收请求、将请求分发至不同的控制器,并负责客户端响应。它的地位相当于 “中央调度器”,简化了组件间的耦合,是 Spring MVC 流程的核心驱动者。

2:HandlerMapping :处理器映射器,根据 uri去匹配查找能处理的 Handler ,并会将请求涉及到的拦截器和 Handler 一起封装。

  • 常见实现:
    • RequestMappingHandlerMapping:处理 @RequestMapping 注解的 Controller 方法(最常用);
    • BeanNameUrlHandlerMapping:根据 Bean 的名称(需以 / 开头)映射请求 URL。

3:HandlerAdapter:处理器适配器,根据 HandlerMapping 找到的 Handler ,适配执行对应的 Handler;

  • 常见实现:
    • RequestMappingHandlerAdapter:适配 @Controller + @RequestMapping 注解的处理器(最常用);
    • SimpleControllerHandlerAdapter:适配实现 Controller 接口的处理器。

4:Handler :请求处理器,处理实际请求的处理器。

5:ViewResolver :视图解析器,根据 Handler返回的逻辑视图名称,解析并渲染真正的视图文件,并传递给 DispatcherServlet响应至客户端

        这些组件通过 DispatcherServlet 串联,形成完整流程。这种设计通过接口解耦,使各组件可灵活替换(如替换视图解析器支持不同模板引擎),体现了 Spring 的 “开闭原则”。

二、Spring Mvc 的执行流程。

        如图所示:

        SpringMVC 是基于 MVC 设计模式的 Web 框架,其核心是通过 DispatcherServlet(前端控制器)协调多个组件完成请求处理。以下从执行流程的 11 个核心步骤展开,下面我们详细解析各环节的实现逻辑。

1. 请求入口:用户请求到达 DispatcherServlet

用户发送的 HTTP 请求(GET/POST 等)首先被 DispatcherServlet 接收。DispatcherServlet 继承自 HttpServlet,其核心处理逻辑在 doDispatch() 方法中,所有请求最终都会进入该方法:

// DispatcherServlet 
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null; 
    boolean multipartRequestParsed = false;
    try {
        ModelAndView mv = null;
        Exception dispatchException = null;
        try {
          
            processedRequest = checkMultipart(request);
            multipartRequestParsed = (processedRequest != request);
            //  找到当前请求对应的处理器执行链(核心步骤)
            mappedHandler = getHandler(processedRequest);
            if (mappedHandler == null) {
                // 没有找到处理器,返回 404
                noHandlerFound(processedRequest, response);
                return;
            }
            //  找到支持当前处理器的适配器(核心步骤)
            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

            //  执行拦截器的 preHandle 方法(前置处理)
            if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                return; // 若有拦截器返回 false,终止流程
            }
            //  调用处理器(Controller)并返回 ModelAndView(核心步骤)
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
            //  处理默认视图名(若 Controller 未指定视图名)
            applyDefaultViewName(processedRequest, mv);
            //  执行拦截器的 postHandle 方法(后置处理)
            mappedHandler.applyPostHandle(processedRequest, response, mv);
        } catch (Exception ex) {
            dispatchException = ex;
        }
        // 处理结果:渲染视图 + 执行拦截器 afterCompletion(核心步骤)
        processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    } catch (Exception ex) {
        //  异常时执行拦截器的 afterCompletion
        triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
    } finally {
        // 1清理文件上传请求资源
        if (multipartRequestParsed) {
            cleanupMultipart(processedRequest);
        }
    }
}

2. 查找处理器:HandlerMapping 定位处理器

DispatcherServlet 通过 HandlerMapping 接口的实现类(如 RequestMappingHandlerMapping)根据请求 URL 查找对应的处理器(Controller 方法),并封装为 HandlerExecutionChain(包含处理器和拦截器)。

核心源码(getHandler() 方法):

// DispatcherServlet 
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    if (this.handlerMappings != null) {
        // 遍历所有 HandlerMapping,找到第一个匹配的处理器
        for (HandlerMapping mapping : this.handlerMappings) {
            HandlerExecutionChain handler = mapping.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
    }
    return null;
}
  • 关键实现RequestMappingHandlerMapping 会在启动时扫描所有 @Controller 类中的 @RequestMapping 注解,建立 URL 与 Controller 方法的映射关系,请求时直接根据 URL 匹配。
    3. 适配处理器:HandlerAdapter 统一调用接口

    由于处理器(Controller 方法)的类型可能不同(如注解式、接口式),DispatcherServlet 通过 HandlerAdapter 接口适配不同类型的处理器,统一调用方式。

    核心源码(getHandlerAdapter() 方法):

    
    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
        if (this.handlerAdapters != null) {
            for (HandlerAdapter adapter : this.handlerAdapters) {
                // 判断适配器是否支持当前处理器
                if (adapter.supports(handler)) {
                    return adapter;
                }
            }
        }
        throw new ServletException("No adapter for handler [" + handler + "]");
    }

  • 常用适配器RequestMappingHandlerAdapter 用于处理注解式 Controller(@Controller + @RequestMapping),是最常用的实现。
  • 4. 拦截器前置处理:preHandle ()

    HandlerExecutionChain 中的拦截器(HandlerInterceptor)会在处理器执行前调用 preHandle() 方法,可用于权限校验、日志记录等。

    核心源码(applyPreHandle() 方法):

  • // HandlerExecutionChain 
    boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HandlerInterceptor[] interceptors = getInterceptors();
        if (!ObjectUtils.isEmpty(interceptors)) {
            // 正序执行拦截器的 preHandle
            for (int i = 0; i < interceptors.length; i++) {
                HandlerInterceptor interceptor = interceptors[i];
                if (!interceptor.preHandle(request, response, this.handler)) {
                    // 若当前拦截器返回 false,触发后续拦截器的 afterCompletion 并终止
                    triggerAfterCompletion(request, response, null);
                    return false;
                }
                this.interceptorIndex = i; 
            }
        }
        return true;
    }
    5. 执行处理器:调用 Controller 方法

    HandlerAdapter 调用处理器(Controller 方法),执行业务逻辑并返回 ModelAndView(包含视图名和模型数据)。

    以 RequestMappingHandlerAdapter 为例,核心调用逻辑在 invokeHandlerMethod() 方法:

  • 
    protected ModelAndView invokeHandlerMethod(HttpServletRequest request, 
                                              HttpServletResponse response, 
                                              HandlerMethod handlerMethod) throws Exception {
        ServletWebRequest webRequest = new ServletWebRequest(request, response);
        try {
            // 解析请求参数
            WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
            ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
            // 创建 ServletInvocableHandlerMethod 用于执行 Controller 方法
            ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
            invocableMethod.setDataBinderFactory(binderFactory);
            invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
            invocableMethod.setMessageConverters(this.messageConverters); // 
            ModelAndViewContainer mavContainer = new ModelAndViewContainer();
            mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
            modelFactory.initModel(webRequest, mavContainer, invocableMethod);
            mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
            // 执行 Controller 方法(核心)
            invocableMethod.invokeAndHandle(webRequest, mavContainer);
            
            // 返回 ModelAndView
            return getModelAndView(mavContainer, modelFactory, webRequest);
        } finally {
            webRequest.requestCompleted();
        }
    }

  • 结果:Controller 方法执行后,返回 ModelAndView(例如 new ModelAndView("index", "msg", "Hello") 表示视图名为 index,模型数据为 msg=Hello)。
  • 6. 拦截器后置处理:postHandle ()

    处理器执行完成后,HandlerExecutionChain 会调用拦截器的 postHandle() 方法,可用于修改模型数据或视图(在视图渲染前执行)

    7. 解析视图:ViewResolver 解析视图名

    DispatcherServlet 通过 ViewResolver 将 ModelAndView 中的逻辑视图名(如 "index")解析为物理视图对象(如 JSP 路径 /WEB-INF/views/index.jsp)。

    8. 渲染视图:填充模型数据到视图

    View 对象的 render() 方法将模型数据(Model)填充到视图中,生成最终的响应内容(如 HTML)。

    9. 拦截器完成处理:afterCompletion ()

    视图渲染完成后(无论成功或失败),HandlerExecutionChain 会调用拦截器的 afterCompletion() 方法,用于资源清理(如关闭流、释放锁)。

    10. 响应客户端

    最终,渲染后的视图内容通过 HttpServletResponse 返回给用户,完成整个请求流程。

---------------------------------------------------------------------------------------------------------------------------------

  • 核心设计模式与总结

  • 设计模式

    • 前端控制器模式(DispatcherServlet 统一调度);
    • 适配器模式(HandlerAdapter 适配不同处理器);
    • 责任链模式(拦截器链 HandlerExecutionChain)。
  • 流程核心
    以 DispatcherServlet 为中心,通过 HandlerMapping 找处理器、HandlerAdapter 执行处理器、ViewResolver 解析视图,配合拦截器实现请求的完整生命周期管理,各组件通过接口解耦,体现了 Spring “高内聚、低耦合” 的设计思想。今天依旧是深蹲不写BUG,我们继续努力!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值