SpringMVC 工作原理深入解析

章节一:工作原理剖析

一、前言

**核心结论:**SpringMVC 采用「前端控制器」模式,所有请求先由 DispatcherServlet 统一接收,再通过九大组件协同完成请求处理、视图渲染与响应返回。

二、九大核心组件

1、DispatcherServlet

前端控制器,所有请求的入口点

2、HandlerMapping

根据URL找到对应的处理器

3、HandlerAdapter

适配不同处理器的调用方式

4、ViewResolver

解析视图名称到具体视图

5、HandlerExceptionResolver

全局异常处理

6、LocaleResolver

处理国际化 🎨

7、ThemeResolver

解析主题(如皮肤)

8、MultipartResolver

处理文件上传

9、FlashMapManager

重定向参数传递

三、请求处理全流程

1. 请求接收

用户请求到达 DispatcherServlet,所有请求都先经过这个前端控制器。

2. 处理器映射

DispatcherServlet 调用 HandlerMapping,根据URL找到对应的Controller方法。

3. 处理器适配

通过 HandlerAdapter 适配不同类型的Controller方法,确保统一调用。

4. 控制器执行

实际执行业务逻辑,返回 ModelAndView 对象(包含数据和视图名)。

5. 视图解析

ViewResolver 将逻辑视图名解析为具体的视图实现(如JSP)。

6. 视图渲染

将 Model 中的数据填充到视图中,生成最终的HTML响应。

7. 响应返回

DispatcherServlet 将渲染后的视图返回给客户端。

四、关键源码解析

java 复制代码
// DispatcherServlet.doDispatch() 核心流程
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 1. 获取处理器
    HandlerExecutionChain mappedHandler = getHandler(processedRequest);
    
    // 2. 获取适配器
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    
    // 3. 执行处理器
    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    
    // 4. 视图解析与渲染
    processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}

五、注解驱动实现

@Controller + @RequestMapping

通过注解方式替代传统接口开发,简化配置:
@Controller 标识为控制器, @RequestMapping映射请求路径

示例代码

java 复制代码
@Controller
@RequestMapping("/user")
public class UserController {
    @GetMapping("/list")
    public String list(Model model) {
        List<User> users = userService.findAll();
        model.addAttribute("users", users);
        return "userList"; // 返回视图名
    }
}

章节二、SpringMVC 源码剖析

SpringMVC 是 Spring 框架中用于构建 Web 应用程序的核心模块,它基于经典的 MVC(Model-View-Controller)设计模式,提供了一个灵活、可配置的请求处理框架。理解其源码,是掌握其高级特性和进行深度定制的关键。

一、源码入口:doDispatch 方法

DispatcherServlet.java

java 复制代码
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 1. 检查是否为文件上传等multipart请求,并进行包装处理
    processedRequest = checkMultipart(request);
    multipartRequestParsed = (processedRequest != request);

    try {
        // 2. 为当前请求确定一个处理器执行链 (HandlerExecutionChain)
        //    该链包含了最终要执行的处理器(handler)和匹配的拦截器(interceptors)
        mappedHandler = getHandler(processedRequest);
        if (mappedHandler == null) {
            // 如果没有找到处理器,则返回404
            noHandlerFound(processedRequest, response);
            return;
        }

        // 3. 获取能处理该handler的适配器 (HandlerAdapter)
        HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

        // 4. 执行处理器执行链中所有拦截器的preHandle方法
        //    如果某个拦截器返回false,则中断流程
        if (!mappedHandler.applyPreHandle(processedRequest, response)) {
            return;
        }

        // 5. 【核心】通过适配器实际调用处理器(handler)方法,处理业务逻辑
        //    并返回包含模型数据和视图信息的ModelAndView对象
        mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

        // 6. 如果当前请求是异步处理的,直接返回
        if (asyncManager.isConcurrentHandlingStarted()) {
            return;
        }

        // 7. 如果没有返回视图名,则设置一个默认的视图名
        applyDefaultViewName(processedRequest, mv);

        // 8. 执行处理器执行链中所有拦截器的postHandle方法
        mappedHandler.applyPostHandle(processedRequest, response, mv);

    } catch (Exception ex) {
        // 异常处理...
        dispatchException = ex;
    } catch (Throwable err) {
        // 错误处理...
        dispatchException = new NestedServletException("Handler dispatch failed", err);
    }

    // 9. 处理分发结果,进行视图渲染,并触发拦截器的afterCompletion方法
    processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
java 复制代码
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    if (this.handlerMappings != null) {
        // 遍历所有配置的HandlerMapping
        for (HandlerMapping mapping : this.handlerMappings) {
            // 调用HandlerMapping的getHandler方法
            HandlerExecutionChain handler = mapping.getHandler(request);
            if (handler != null) {
                // 找到第一个匹配的处理器链即返回
                return handler;
            }
        }
    }
    return null; // 未找到任何匹配的处理器
}
java 复制代码
// RequestMappingHandlerAdapter.java
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
                                           HttpServletResponse response,
                                           HandlerMethod handlerMethod) throws Exception {

    // 1. 将 Servlet 原生的 request/response 包装成 Spring 的 NativeWebRequest
    ServletWebRequest webRequest = new ServletWebRequest(request, response);

    try {
        // 2. 数据绑定与验证:将请求参数绑定到方法参数上(@RequestParam, @RequestBody等)
        WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
        ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

        // 3. 创建 ServletInvocableHandlerMethod,它是实际执行控制器方法的对象
        ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
        // 设置参数解析器(解析@RequestParam, @PathVariable等)
        invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
        // 设置返回值处理器(处理@ResponseBody, ModelAndView等)
        invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);

        // 4. 初始化模型(Model)
        ModelAndViewContainer mavContainer = new ModelAndViewContainer();
        mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
        modelFactory.initModel(webRequest, mavContainer, invocableMethod);

        // 5. 【核心调用】执行控制器方法,并处理返回值
        invocableMethod.invokeAndHandle(webRequest, mavContainer);

        // 6. 将 ModelAndViewContainer 转换为 ModelAndView 对象并返回
        return getModelAndView(mavContainer, modelFactory, webRequest);
    } finally {
        webRequest.requestCompleted();
    }
}

二、核心组件详解

SpringMVC 的强大之处在于其高度模块化和可插拔的组件设计。理解这些核心组件是读懂源码的基础。

组件 核心接口/类 主要职责
处理器映射器 HandlerMapping 根据请求信息(URL、Method等)查找对应的处理器(Handler)。
处理器适配器 HandlerAdapter 以统一的方式调用不同类型的处理器(如 @Controller, HttpRequestHandler)。
视图解析器 ViewResolver 将逻辑视图名(如 "home")解析为具体的视图对象(如 JSP, Thymeleaf模板)。
处理器异常解析器 HandlerExceptionResolver 统一处理控制器执行过程中抛出的异常,进行友好化转换。
HTTP消息转换器 HttpMessageConverter 负责 HTTP 请求/响应体与 Java 对象之间的相互转换(如 JSON ↔ Object)。

三、设计模式与架构思想

SpringMVC 源码是经典设计模式的教科书式应用,理解这些模式能让你更深刻地领会其设计精髓。

  • 前端控制器模式 (Front Controller)DispatcherServlet 作为单一入口,统一接收所有请求,简化了请求处理流程。

  • 策略模式 (Strategy)HandlerMapping, HandlerAdapter, ViewResolver 等都是策略接口,允许灵活替换实现。

  • 模板方法模式 (Template Method)AbstractHandlerMethodAdapter.handle 定义了处理请求的骨架,子类实现具体步骤。

  • 责任链模式 (Chain of Responsibility)HandlerExecutionChain 和拦截器 (HandlerInterceptor) 构成了一个处理链,请求依次通过。

  • 适配器模式 (Adapter)HandlerAdapter 将不同处理器(如 Controller、HttpRequestHandler)的调用方式统一起来。

3.1、单例模式 (Singleton)

*核心实现类: DispatcherServlet
**作用:*确保整个Web应用生命周期中只有一个DispatcherServlet实例处理所有请求。

java 复制代码
// DispatcherServlet 单例实现核心
public class DispatcherServlet extends FrameworkServlet {
    // 单例实例通过Spring容器管理
    private static volatile DispatcherServlet instance;
    
    /**
     * 获取单例实例的方法(Spring容器内部实现)
     * @return DispatcherServlet的唯一实例
     * 说明:Spring通过IoC容器确保在整个应用上下文中
     * 只有一个DispatcherServlet bean实例
     */
    public static DispatcherServlet getInstance() {
        if (instance == null) {
            synchronized (DispatcherServlet.class) {
                if (instance == null) {
                    instance = new DispatcherServlet();
                }
            }
        }
        return instance;
    }
    
    @Override
    protected WebApplicationContext createWebApplicationContext(
            WebApplicationContext parent) {
        // 返回全局唯一的Web应用上下文
        return getWebApplicationContext();
    }
}

3.2、工厂方法模式 (Factory Method)

*核心实现类: RequestMappingHandlerMapping
**作用:*根据请求映射规则创建对应的处理器执行链。

java 复制代码
public class RequestMappingHandlerMapping implements HandlerMapping {
    
    /**
     * 工厂方法:根据HTTP请求创建处理器执行链
     * @param request HTTP请求对象
     * @return HandlerExecutionChain 处理器执行链
     * 说明:该方法作为工厂方法,负责根据请求的URL、方法类型等信息
     * 创建对应的HandlerMethod对象,并将其包装成执行链
     */
    @Override
    public HandlerExecutionChain getHandler(HttpServletRequest request) {
        // 1. 解析请求路径和方法
        String requestURI = request.getRequestURI();
        String httpMethod = request.getMethod();
        
        // 2. 查找匹配的Controller方法(工厂方法的核心逻辑)
        HandlerMethod handlerMethod = lookupHandlerMethod(requestURI, httpMethod);
        
        // 3. 创建并返回处理器执行链
        if (handlerMethod != null) {
            HandlerExecutionChain chain = new HandlerExecutionChain(handlerMethod);
            // 添加拦截器
            chain.addInterceptors(getInterceptors());
            return chain;
        }
        return null;
    }
    
    private HandlerMethod lookupHandlerMethod(String requestURI, String method) {
        // 具体的查找逻辑:遍历所有@Controller类中的@RequestMapping方法
        // 匹配URL模式和方法类型,返回对应的HandlerMethod
        // 这是工厂方法的具体实现
    }
}

3.3、适配器模式 (Adapter)

核心实现类: HandlerAdapter及其实现类(如RequestMappingHandlerAdapterSimpleControllerHandlerAdapter

java 复制代码
public interface HandlerAdapter {
    /**
     * 检查是否支持该处理器类型
     * @param handler 待处理的处理器对象
     * @return 如果支持返回true,否则false
     * 说明:适配器模式的关键方法,用于判断该适配器
     * 能否处理特定类型的Controller
     */
    boolean supports(Object handler);
    
    /**
     * 处理请求的核心方法
     * @param request HTTP请求
     * @param response HTTP响应
     * @param handler 处理器对象
     * @return ModelAndView 模型和视图对象
     * @throws Exception 处理过程中可能抛出的异常
     * 说明:将不同Controller的统一接口适配到标准的
     * handle方法,实现多态调用
     */
    ModelAndView handle(HttpServletRequest request, 
                       HttpServletResponse response, 
                       Object handler) throws Exception;
}
java 复制代码
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
    
    /**
     * 支持传统的Controller接口实现
     * 说明:这是适配器模式的具体实现,将Spring MVC早期版本中
     * 的Controller接口适配到统一的HandlerAdapter接口
     */
    @Override
    public boolean supports(Object handler) {
        return (handler instanceof Controller);
    }
    
    @Override
    public ModelAndView handle(HttpServletRequest request,
                              HttpServletResponse response, 
                              Object handler) throws Exception {
        // 类型转换并调用Controller的handleRequest方法
        return ((Controller) handler).handleRequest(request, response);
    }
}

3.4、模板方法模式 (Template Method)

核心实现类: FrameworkServlet中的processRequestdoService方法

java 复制代码
public abstract class FrameworkServlet extends HttpServlet {
    
    /**
     * 模板方法:定义请求处理的骨架
     * @param request HTTP请求
     * @param response HTTP响应
     * 说明:这是模板方法模式的典型应用,定义了处理HTTP请求的
     * 固定流程,具体步骤由子类实现
     */
    protected final void processRequest(HttpServletRequest request,
                                       HttpServletResponse response) {
        // 1. 记录请求开始时间(模板方法的固定步骤)
        long startTime = System.currentTimeMillis();
        
        // 2. 设置本地化上下文(可被子类覆盖的钩子方法)
        LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
        LocaleContext localeContext = buildLocaleContext(request);
        
        try {
            // 3. 执行实际的服务处理(抽象方法,由子类实现)
            doService(request, response);
            
            // 4. 发布请求处理事件(模板方法的固定步骤)
            publishRequestHandledEvent(request, startTime);
            
        } finally {
            // 5. 清理资源(模板方法的固定步骤)
            resetContextHolders(request, previousLocaleContext);
        }
    }
    
    /**
     * 抽象方法:具体的服务处理逻辑
     * 说明:这是模板方法中的可变部分,由DispatcherServlet等子类实现
     * 不同的子类可以提供不同的具体实现
     */
    protected abstract void doService(HttpServletRequest request,
                                     HttpServletResponse response) throws Exception;
}

3.5、策略模式 (Strategy)

核心实现类: ViewResolver接口及其多个实现类(InternalResourceViewResolverThymeleafViewResolver等)

策略实现类 解析的视图类型 核心方法
InternalResourceViewResolver JSP页面 resolveViewName()
ThymeleafViewResolver Thymeleaf模板 resolveViewName()
FreeMarkerViewResolver FreeMarker模板 resolveViewName()
ContentNegotiatingViewResolver 多种视图(内容协商) resolveViewName()
java 复制代码
public class InternalResourceViewResolver implements ViewResolver {
    
    private String prefix = "";
    private String suffix = "";
    
    /**
     * 策略模式的具体实现:解析JSP视图
     * @param viewName 视图名称
     * @param locale 本地化信息
     * @return View 视图对象
     * 说明:这是视图解析策略的一种具体实现,负责将逻辑视图名
     * 转换为实际的JSP资源路径
     */
    @Override
    public View resolveViewName(String viewName, Locale locale) {
        // 构建完整的资源路径:前缀 + 视图名 + 后缀
        String viewPath = prefix + viewName + suffix;
        
        // 创建并返回InternalResourceView实例
        InternalResourceView view = new InternalResourceView(viewPath);
        view.setServletContext(getServletContext());
        
        return view;
    }
    
    // 设置前缀和后缀的方法
    public void setPrefix(String prefix) {
        this.prefix = (prefix != null ? prefix : "");
    }
    
    public void setSuffix(String suffix) {
        this.suffix = (suffix != null ? suffix : "");
    }
}

四、设计模式的协同工作

在SpringMVC的请求处理流程中,这些设计模式不是孤立存在的,而是相互协作形成一个完整的处理链。理解它们如何协同工作,才能真正掌握SpringMVC的精髓。

完整请求处理流程中的模式协作

  • 1. 请求接收阶段 :单例模式的DispatcherServlet接收所有HTTP请求

  • 2. 处理器映射阶段 :工厂方法模式的HandlerMapping根据URL创建处理器执行链

  • 3. 处理器适配阶段 :适配器模式的HandlerAdapter将不同Controller适配到统一接口

  • 4. 拦截器处理阶段 :责任链模式的HandlerInterceptor按顺序执行预处理和后处理

  • 5. 视图解析阶段 :策略模式的ViewResolver根据配置选择具体的视图解析策略

  • 6. 响应渲染阶段 :模板方法模式的AbstractView定义视图渲染的标准流程

**设计模式的价值体现:**这种多模式协作的架构让SpringMVC既保持了框架的稳定性(通过单例、模板方法),又提供了极大的灵活性(通过工厂方法、策略模式)。开发者可以在不修改框架核心代码的情况下,通过实现特定接口或配置不同策略来定制自己的处理逻辑。

五、深入理解的最佳实践

5.1、源码阅读建议

  1. DispatcherServlet.doDispatch()方法开始跟踪完整的请求处理流程

  2. 重点关注各个接口的定义和实现类的关系

  3. 使用调试模式观察设计模式在实际运行时的表现

  4. 对比不同设计模式实现类的代码结构和设计思路

5.2、实际应用技巧

  1. 自定义HandlerInterceptor实现权限验证、日志记录等横切关注点

  2. 实现自定义的ViewResolver支持新的模板引擎

  3. 通过HandlerAdapter扩展支持新的Controller类型

  4. 利用模板方法模式统一处理异常和资源清理

六、写在最后的话

SpringMVC的设计模式实现不仅体现了软件工程的最佳实践,更为框架的扩展性和维护性奠定了坚实基础。通过深入理解这些实现类及其协作方式,开发者可以更好地利用框架特性,甚至在必要时进行深度定制和扩展。

正如计算机科学家Grady Booch所言:"好的架构让系统易于理解、易于修改、易于扩展。" SpringMVC通过精心设计的设计模式实现,正是这一理念的完美体现。

相关推荐
sanggou2 小时前
Spring Cloud负载均衡组件到底是哪一个?
spring·spring cloud·负载均衡
xiaoye37082 小时前
Spring Bean 生命周期自定义扩展示例
java·spring boot·spring
弹简特2 小时前
【JavaEE17-后端部分】 MyBatis 入门第一篇:准备工作与第一个查询
spring boot·spring·mybatis
逆境不可逃3 小时前
【从零入门23种设计模式15】行为型之解释器模式
设计模式·解释器模式
geovindu3 小时前
python: Adapter Pattern
java·python·设计模式·适配器模式
蜜獾云3 小时前
设计模式之工厂方法模式(5):稍微复杂一点的工厂模式
java·设计模式·工厂方法模式
Voyager_43 小时前
吃透设计模式:从原理到落地(如何选型),Java/Spring开发场景
java·spring·设计模式
zlp19923 小时前
软考(系统架构师)-软件架构设计之设计模式
设计模式·软考高级·软考·系统架构师
6+h4 小时前
【Spring】深度剖析AOP
java·后端·spring