首页 技术 正文
技术 2022年11月12日
0 收藏 490 点赞 4,223 浏览 2487 个字

一、背景

  最近在项目中遇到了启动时出现加载service注解注入失败的问题,后来经过不懈努力发现了是因为web.xml配置文件中的元素加载顺序导致的,那么就抽空研究了以下tomcat在启动时web.xml文件中元素的加载顺序,现在和大家分享。

二、问题剖析和研究结果

  遇到这种问题的时候,一般看源码是最直接和最权威的获取答案的方式,根据tomcat架构设计Context的实现类是StandardContext,全称org.apache.catalina.core.StandardContext。看到其实现Lifecycle接口,我们在StandardContext中找到startInternal方法,下面给出我把暂时无用的代码去掉后的注释版源码:

 /**
* Start this component and implement the requirements
* of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
@Override
protectedsynchronized void startInternal() throwsLifecycleException {
//设置webappLoader 代码省略 // Standard container startup 代码省略   try{     // Set up the context init params
    //初始化context-param节点数据
    mergeParameters();     // Configure and call application event listeners
    //配置和调用应用程序事件listeners
    if(ok) {
      if(!listenerStart()) {
        log.error("Error listenerStart");
        ok = false;
      }
    }     // Configure and call application filters
    //配置和调用应用程序filters
    if(ok) {
      if(!filterStart()) {
        log.error("Error filterStart");
        ok = false;
      }
    }     // Load and initialize all "load on startup" servlets
    //加载和初始化配置在load on startup的servlets
    if(ok) {
      loadOnStartup(findChildren());
    }     // Start ContainerBackgroundProcessor thread
    super.threadStart();
  }finally{
    // Unbinding thread
    unbindThread(oldCCL);
  } }

那我们接着归纳和整理一下代码:

  1.首先初始化context-param节点

  2.接着配置和调用listeners 并开始监听

  3.然后配置和调用filters filters开始起作用

  4.最后加载和初始化配置在load on startup的servlets

即元素加载顺序为:

context-param --> listeners --> filters --> servlets

注意:

  1.该加载顺序并不会受元素在web.xml文件中的位置的影响。

  2.但对于某类配置节而言,与它们出现的顺序是有关的。以 filter 为例,web.xml 中当然可以定义多个 filter,与 filter 相关的一个配置节是 filter-mapping,这里一定要注意,对于拥有相同 filter-name 的 filter 和 filter-mapping 配置节而言,filter-mapping 必须出现在 filter 之后,否则当解析到 filter-mapping 时,它所对应的 filter-name 还未定义。web 容器启动时初始化每个 filter 时,是按照 filter 配置节出现的顺序来初始化的,当请求资源匹配多个 filter-mapping 时,filter 拦截资源是按照 filter-mapping 配置节出现的顺序来依次调用 doFilter() 方法的。

接着让我们来回忆一下web项目的启动顺序

  1.web容器读取web.xml配置文件,并首先读取<context-param>和<listener>两个结点。

  2.容器创建一个ServletContext(servlet上下文),该web项目的所有部分都将共享这个上下文。

  3.容器将<context-param>转换为键值对,并交给servletContext。

  4.容器按照load on startup中的启动顺序创建<listener>中的类实例,创建监听器。

关于load on startup

  load-on-startup 元素在web应用启动的时候指定了servlet被加载的顺序,它的值必须是一个整数。

  如果它的值是一个负整数或是这个元素不存在,那么容器会在该servlet被调用的时候,加载这个servlet 。

  如果值是正整数或零,容器在配置的时候就加载并初始化这个servlet,容器必须保证值小的先被加载。如果值相等,容器可以自动选择先加载谁。

  正数的值越小,启动该servlet的优先级越高。

三、总结

  通过研究源码我们明白了web.xml中各个元素的加载顺序,再遇到这种问题,我们就可以很快的定位出问题所在了。由此也发现和体会到了研究源码是一种很好的习惯也是解决问题不可缺少的方式。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,487
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,903
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,736
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,487
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,127
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,289