千家信息网

如何进行SpringMVC的DispatcherServlet源码分析

发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,本篇文章为大家展示了如何进行SpringMVC的DispatcherServlet源码分析,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。DispatcherS
千家信息网最后更新 2025年12月02日如何进行SpringMVC的DispatcherServlet源码分析

本篇文章为大家展示了如何进行SpringMVC的DispatcherServlet源码分析,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

DispatcherServlet源码分析

SpringMVC核心就是DispatcherServlet,所有得请求都会转发到DispatcherServlet,然后再通过DispatcherServlet执行具体得控制层(Handler)返回ModelAndView给客户端视图展示。

// 3. 将我们的DispatcherServlet 注入到 serlvet容器中ServletRegistration.Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(app));// 4.填写url路径映射dynamic.addMapping("/");

DispatcherServlet其实就是一个Servlet类,无非就是包装一层,通过url能够映射找到我们得SpringMvc中定义得请求方法。

源代码分析:

  1. 类的集成关系

DispatcherServlet继承FrameworkServlet继承HttpServlet

面向基本上思想 重写 先走父类 ,在走子类。

得出答案:先看HttpServlet在找到我们最后的子类

protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {    this.processRequest(request, response);}

DispatcherServlet与Servlet关系

关系:DispatcherServlet继承FrameworkServlet继承HttpServlet

流程执行关系:

HttpServlet service方法 判断请求方法的类型

FrameworkServlet doService

DispatcherServlet doService

DispatcherServlet的初始化

在servlet初始化阶段会调用其init方法,所以我们首先要查看在DispatcherServlet中是否重写了init方法。我们在其父类HttpServletBean中找到该方法

public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware { ....    public final void init() throws ServletException {        if (this.logger.isDebugEnabled()) {            this.logger.debug("Initializing servlet '" + this.getServletName() + "'");        }        //解析init-param并封装至pvs中PropertyValues pvs = new HttpServletBean.ServletConfigPropertyValues(this.getServletConfig(), this.requiredProperties);        if (!pvs.isEmpty()) {            try {                //将当前的servlet类转换为一个BeanWrapper,从而能够以Spring的方式来对init-param的值进行注入BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);                ResourceLoader resourceLoader = new ServletContextResourceLoader(this.getServletContext());                //注册自定义属性编辑器,一旦遇到Resource类型的属性会使用ResourceEditor进行解析bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.getEnvironment()));                //空实现,留给子类覆盖this.initBeanWrapper(bw);                //属性注入bw.setPropertyValues(pvs, true);            } catch (BeansException var4) {                if (this.logger.isErrorEnabled()) {                    this.logger.error("Failed to set bean properties on servlet '" + this.getServletName() + "'", var4);                }                throw var4;            }        }        //留给子类扩展this.initServletBean();        if (this.logger.isDebugEnabled()) {            this.logger.debug("Servlet '" + this.getServletName() + "' configured successfully");        }    }....}

DispatcherServlet的初始化过程主要是通过将当前的Servlet类型实例转换为BeanWrapper类型实例,以便使用Spring中提供的注入功能进行对应属性的注入。

我们看下servletBean的初始化,HttpServletBean其父类FrameworkServlet覆盖了它的initServletBean函数,如下:

protected final void initServletBean() throws ServletException {    this.getServletContext().log("Initializing Spring FrameworkServlet '" + this.getServletName() + "'");    if (this.logger.isInfoEnabled()) {        this.logger.info("FrameworkServlet '" + this.getServletName() + "': initialization started");    }    //计时器,统计初始化的执行时间long startTime = System.currentTimeMillis();    try {        //关键的初始化逻辑委托给了这个方法this.webApplicationContext = this.initWebApplicationContext();        //设计为子类覆盖this.initFrameworkServlet();    } catch (RuntimeException | ServletException var5) {        this.logger.error("Context initialization failed", var5);        throw var5;    }    if (this.logger.isInfoEnabled()) {        long elapsedTime = System.currentTimeMillis() - startTime;        this.logger.info("FrameworkServlet '" + this.getServletName() + "': initialization completed in " + elapsedTime + " ms");    }}

WebApplicationContext 的初始化

initWebApplicationContext函数主要工作就是创建或者刷新WebApplicationContext 实例并对servlet功能所使用的变量进行初始化

protected WebApplicationContext initWebApplicationContext() {    WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());    WebApplicationContext wac = null;    if (this.webApplicationContext != null) {        //context实例在构造函数中被注入wac = this.webApplicationContext;        if (wac instanceof ConfigurableWebApplicationContext) {            ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)wac;            if (!cwac.isActive()) {                if (cwac.getParent() == null) {                    cwac.setParent(rootContext);                }                //刷新上下文环境this.configureAndRefreshWebApplicationContext(cwac);            }        }    }    if (wac == null) {        //根据contextAttribute属性加载webApplicationContextwac = this.findWebApplicationContext();    }    if (wac == null) {        wac = this.createWebApplicationContext(rootContext);    }    if (!this.refreshEventReceived) {        this.onRefresh(wac);    }    if (this.publishContext) {        String attrName = this.getServletContextAttributeName();        this.getServletContext().setAttribute(attrName, wac);        if (this.logger.isDebugEnabled()) {            this.logger.debug("Published WebApplicationContext of servlet '" + this.getServletName() + "' as ServletContext attribute with name [" + attrName + "]");        }    }    return wac;}

刷新方法onRefresh

protected void onRefresh(ApplicationContext context) {    this.initStrategies(context);}

protected void initStrategies(ApplicationContext context) {

initMultipartResolver(context); //初始化上传文件解析器(或者是多部分请求解析器)

initLocaleResolver(context);//初始化本地化解析器

initThemeResolver(context);//初始化主题解析器

initHandlerMappings(context);//初始化处理器映射器

initHandlerAdapters(context);//初始化处理器适配器

initHandlerExceptionResolvers(context);//初始化处理器异常解析器

initRequestToViewNameTranslator(context);//初始化请求到视图名翻译器

initViewResolvers(context);//初始化视图解析器

initFlashMapManager(context);//初始化重定向数据管理器

DispatcherServlet的逻辑处理

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {  ...    try {        try {     ...                //通过url路径地址去查找控制层类方法,如果没有找到的化,直接返回404mappedHandler = this.getHandler(processedRequest);        ....                HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());                String method = request.getMethod();                boolean isGet = "GET".equals(method);               ....                if (!mappedHandler.applyPreHandle(processedRequest, response)) {                    return;                }                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());          ....                mappedHandler.applyPostHandle(processedRequest, response, mv);....}

SpringMVC源码之定位Handler原理

private List handlerMappings;

mappedHandler = this.getHandler(processedRequest);

HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());

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

/** * 请求方法前置拦截,如果返回true 表示会执行到目标方法(请求方法) 如果返回false的情况下 则不会执行目标方法。 */@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {    String token = request.getParameter("token");    System.out.println(">>>>token<<<<:" + token);    if (StringUtils.isEmpty(token)) {        response.setStatus(500);        response.getWriter().print(" token is null");        return false;    }    // 执行我们的请求方法return true;}
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

执行目标方法:

@RequestMapping("/pageIndex")public String pageIndex() {    System.out.println(">>>pageIndex<<<<");    return "pageIndex";}
mappedHandler.applyPostHandle(processedRequest, response, mv);

@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {    System.out.println("<<>>>");    // 请求之后执行。}

DispatcherServlet源码流程分析

1.执行doDispatch

2.调用getHandler方法获取请求目标的方法 也就是 请求url映射路径对应的控制层具体的方法

handlerMappings的作用查找控制器位置,比如xml和注解方式。

3.调用getHandlerAdapter获取控制层适配器 RequestMappingHandlerAdapter

4.执行拦截器前置方法 preHandle() 如果返回为true的话

5.执行实际请求目标方法 返回modeAndView对象

6.执行拦截器PostHandle()方法

7.设置渲染视图层内容

8.执行拦截器afterCompletion方

SpringMVC控制层容器初始化

  1. HttpServletBean init ()方法

  2. FrameworkServlet initServletBean方法→ initWebApplicationContext();

  3. DispatcherServlet onRefresh方法→ initStrategies()方法

protected void onRefresh(ApplicationContext context) {    this.initStrategies(context);}

当我们servlet容器初始化的时候初始化

this.initHandlerMappings(context);

上述内容就是如何进行SpringMVC的DispatcherServlet源码分析,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注行业资讯频道。

方法 控制 源码 分析 子类 就是 属性 目标 实例 类型 处理 内容 函数 处理器 容器 视图 路径 拦截器 功能 技能 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 阿里巴巴数据库战役 网络安全宣传节目表演新闻稿 网络安全应急指挥中心建设项目 网络技术7个要点 服务器的配置与管理技术 热血传奇怎么提高服务器人数 蚂蚁会员网络技术有限公司 网络安全厂商产值 企业网络安全员是专职还是兼职 2018年网络安全法宣传片 虹口区常规软件开发服务要求 服务器怎样连电视 我的世界服务器主城出生点怎么建 国家网络安全法治宣传周的日期 商丘市网络安全课堂 上海港趣网络技术 杭州智能软件开发 河南企业软件开发成本价 黑龙江软件开发费用依据 阿里数据库技术世界第一 白城跑腿app软件开发 计算机网络技术大专就业率 双线服务器是什么游戏 朔州软件开发价格多少 网络安全 网络文明手抄报 中国可信的企业网络安全 数据库统计缺失字段 竹山质量软件开发市场 cs连接数据库实验总结 株洲软件开发工程师大专学校
0