深入理解SpringMVC DispatcherServlet源码及全流程原理

DispatcherServlet概述

DispatcherServlet是SpringMVC的前端控制器(Front Controller),它负责拦截所有进入应用的HTTP请求,分发请求给相应的处理器,并处理返回的响应。DispatcherServlet的主要职责包括:

  • 初始化WebApplicationContext
  • 加载各种组件(如HandlerMapping、HandlerAdapter等)
  • 分发请求
  • 视图解析和渲染

DispatcherServlet初始化

DispatcherServlet的初始化过程包括创建和配置Spring的WebApplicationContext以及加载各种必要的组件。下面是 DispatcherServlet初始化的主要步骤:

  1. 初始化WebApplicationContext:

    protected WebApplicationContext initWebApplicationContext() {
    // 获取现有的WebApplicationContext
    WebApplicationContext rootContext =
    WebApplicationContextUtils.getWebApplicationContext(getServletContext());

    复制代码
     WebApplicationContext wac = createWebApplicationContext(rootContext);
     // 配置WebApplicationContext
     configureAndRefreshWebApplicationContext(wac);
     return wac;

    }
    ​

  2. 加载配置文件和初始化组件:

    protected void initStrategies(ApplicationContext context) {
    initMultipartResolver(context);
    initLocaleResolver(context);
    initThemeResolver(context);
    initHandlerMappings(context);
    initHandlerAdapters(context);
    initHandlerExceptionResolvers(context);
    initRequestToViewNameTranslator(context);
    initViewResolvers(context);
    initFlashMapManager(context);
    }
    ​

请求处理流程

当一个HTTP请求到达时,DispatcherServlet将按以下步骤处理请求:

  1. 请求接收:

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    ModelAndView mv = null;
    Exception dispatchException = null;

    复制代码
     try {
         // 检查并包装Multipart请求
         processedRequest = checkMultipart(request);
    
         // 获得处理器
         mappedHandler = getHandler(processedRequest);
         if (mappedHandler == null) {
             noHandlerFound(processedRequest, response);
             return;
         }
    
         // 获得处理器适配器
         HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    
         // 执行处理器
         mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    
         // 处理视图
         processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
     }
     catch (Exception ex) {
         dispatchException = ex;
         processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
     }

    }
    ​

  2. 检查Multipart请求:

    protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
    if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
    return this.multipartResolver.resolveMultipart(request);
    }
    return request;
    }
    ​

  3. 获取处理器:

    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    for (HandlerMapping hm : this.handlerMappings) {
    HandlerExecutionChain handler = hm.getHandler(request);
    if (handler != null) {
    return handler;
    }
    }
    return null;
    }
    ​

  4. 获取处理器适配器:

    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    for (HandlerAdapter ha : this.handlerAdapters) {
    if (ha.supports(handler)) {
    return ha;
    }
    }
    throw new ServletException("No adapter for handler [" + handler + "]");
    }
    ​

  5. 处理视图:

    protected void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
    HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
    if (exception != null) {
    if (mv == null) {
    throw exception;
    }
    mv.addObject("exception", exception);
    }

    复制代码
     if (mv != null) {
         render(mv, request, response);
     }

    }
    ​

处理器映射

处理器映射(Handler Mapping)负责将请求URL映射到相应的处理器。常用的处理器映射有:

  • RequestMappingHandlerMapping:基于注解的处理器映射。

  • BeanNameUrlHandlerMapping:基于Bean名称的处理器映射。

    public HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
    HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
    return handlerMethod != null ? new HandlerExecutionChain(handlerMethod) : null;
    }
    ​

处理器适配

处理器适配(Handler Adapter)负责调用处理器方法。常用的处理器适配有:

  • RequestMappingHandlerAdapter:适配使用@RequestMapping注解的方法。

  • HttpRequestHandlerAdapter:适配实现HttpRequestHandler接口的处理器。

    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    return ((HandlerMethod) handler).invokeForRequest(request, response);
    }
    ​

视图解析

视图解析(View Resolver)负责将逻辑视图名称解析为实际视图对象,并渲染视图。常用的视图解析器有:

  • InternalResourceViewResolver:解析JSP视图。

  • ThymeleafViewResolver:解析Thymeleaf视图。

    public View resolveViewName(String viewName, Locale locale) throws Exception {
    return getView(viewName, locale);
    }

    protected View getView(String viewName, Locale locale) throws Exception {
    return (viewName != null ? new InternalResourceView(viewName) : null);
    }

相关推荐
鸽鸽程序猿2 天前
【项目】【在线判题系统】竞赛发布与撤销发布
状态模式
lemon_sjdk2 天前
从一段真实的 Electron IM 前端代码,看高级前端的工程化修养
前端·electron·状态模式·im
Nebula_g2 天前
云禾外卖补充—项目整体后端运行逻辑-对流程的更深层次理解
java·开发语言·网络·数据库·状态模式·javase
Wang's Blog2 天前
Java 项目实战: 交友项目:登录链路回顾与今日任务地图
java·开发语言·状态模式·交友
Java后端的Ai之路2 天前
14、ReactJS - 路由(Router)
前端·react.js·状态模式
星恒随风2 天前
Linux线程概念详解:从分页存储、页表、MMU与TLB,深入理解线程和进程的区别与联系
linux·运维·笔记·学习·状态模式
溪语流沙3 天前
【Web全栈进阶】前端对接新契约:信封解包 + 统一错误处理
前端·vue.js·python·状态模式·fastapi
积流成海3 天前
JSON 格式化:语法校验与错误定位实践
json·状态模式·盘子工具站
鸽鸽程序猿3 天前
【项目】【在线判题系统】竞赛新增
状态模式
const_qiu4 天前
第 2.5 章 2.5.6:前端登录、Token 无感续签与路由守卫
java·前端·人工智能·状态模式