jetty学习2-WebAppContext

本文详细介绍了Jetty Web应用的启动过程,包括关键组件如webAppContext的作用、配置加载及解析、类加载机制等内容。重点阐述了Jetty如何管理和初始化servlet上下文。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.概述

jetty的web工程主要完成servlet中context的管理,war包中web.xml中文件的解析和加载,类加载器等一些功能。

 

2. 类图和解释

webcontext1

webAppContext是中心,其中包括classloader,configuration和metadata三个主要的内容,classloadee后面再说,configuration主要是对一些配置的应用,比如调用加载器加载jar包,根据web.xml中的配置初始化servlet等等。metadata主要是元数据的定义和处理,展开类图如下:

ctx2

其中descriptor主要完成xml文件的解析,这里包括web.xml,webdefault.xml,web-fragment.xml等,然后DescriptorProcessor主要是将解析好的文件转换为需要使用的数据结构,或者设置context等的一些相应的值。

 

3.启动过程

 

 

server,connector,handler等都继承了abstractLifeCycle(实现LifeCycle接口)。

  1. server的dostart过程包括:启动threadPool,启动handler,启动connector(分别调用它们的doStart方法)
  2. hanlder(webappContext)的doStart方法又包括如下步骤:
     
                preConfigure();
              super.doStart();
              postConfigure();
            
  3. preConfigure()完成的主要工作包括:初始化所有的Configuration,定义systemClass和serverClass,创建webappClassLoader,调用configuration的preconfigure方法。其中WebInfConfiguration主要完成将war包解压的临时文件夹,根据定义加载一些控制扫描jar包的顺序(比如扫描jar包中的web-fragment.xml),   webxmlConfiguration主要完成webdefault.xml,web.xml和web-fragment.xml文件的resource定位和加载。还有几个在此就不详述了。
             loadConfigurations();
    
            // Setup system classes
            loadSystemClasses();
            
            // Setup server classes
            loadServerClasses();
    
            // Configure classloader
            _ownClassLoader=false;
            if (getClassLoader()==null)
            {
                WebAppClassLoader classLoader = new WebAppClassLoader(this);
                setClassLoader(classLoader);
                _ownClassLoader=true;
            }
    
            if (Log.isDebugEnabled())
            {
                ClassLoader loader = getClassLoader();
                Log.debug("Thread Context class loader is: " + loader);
                loader=loader.getParent();
                while(loader!=null)
                {
                    Log.debug("Parent class loader is: " + loader);
                    loader=loader.getParent();
                }
            }
          
            // Prepare for configuration     
            for (int i=0;i<_configurations.length;i++)
                _configurations[i].preConfigure(this);
  4. start方法先将classloader设置到线程上下文加载器,然后调用startContext,分为以下3个步骤
 protected void startContext()
        throws Exception
    {
        configure();
        
        //resolve the metadata
        _metadata.resolve(this);
        
        super.startContext();
    }
  • configure步骤主要调用各个configuration的configure方法,其中webinfconfiguration主要完成两件事情,吧WEB-INF的class文件夹和lib文件夹下得jar加入到webappClassloader的classpath中,然后读取RESOURCE_URLS,设置BaseResource。webxmlconfiguration主要addDescriptorProcessor。
  • metadata.resolve主要完成web.xml(包括servlet注解)中定义的filter,servlet等得解析和初始化化(比如解析到servelet,就会load这个class等),这里一个stranderProcess可以处理webDefaultDescriptor,WebDescriptor等多个文件,处理过程一样,只是处理内容不同。这里以后再扩展一下。
  • 通知所有的contextlistener发生了contextInitialized(event)事件。初始化servletHandler,securityhandler和sessionHandler,并把他们链接起来,最后调用_servletHandler.initialize();,从而调用各个servletHolder的dostart。

 

4.ClassLoad机制

jetty的classload机制很简单,对于system(系统类)的class,使用jdk的方式(双亲委派)加载,对于server(服务器类,app不可见)的class,   ,对于app的class,使用WebAppClassloader来加载,核心代码如下:

 @Override
    protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
    {
        Class<?> c= findLoadedClass(name);
        ClassNotFoundException ex= null;
        boolean tried_parent= false;
        
        boolean system_class=_context.isSystemClass(name);
        boolean server_class=_context.isServerClass(name);
        
        if (system_class && server_class)
        {
            return null;
        }
        
        if (c == null && _parent!=null && (_context.isParentLoaderPriority() || system_class) && !server_class)
        {
            tried_parent= true;
            try
            {
                c= _parent.loadClass(name);
                if (Log.isDebugEnabled())
                    Log.debug("loaded " + c);
            }
            catch (ClassNotFoundException e)
            {
                ex= e;
            }
        }

        if (c == null)
        {
            try
            {
                c= this.findClass(name);
            }
            catch (ClassNotFoundException e)
            {
                ex= e;
            }
        }

        if (c == null && _parent!=null && !tried_parent && !server_class )
            c= _parent.loadClass(name);

        if (c == null)
            throw ex;

        if (resolve)
            resolveClass(c);

        if (Log.isDebugEnabled())
            Log.debug("loaded " + c+ " from "+c.getClassLoader());
        
        return c;
    }

 

其中=_context.isSystemClass(name)方法是查看是否为systemclass,systemclass都通过正则的方式定义在context中了(通过解析配置systemclass名称的字符串得到)

    public boolean isSystemClass(String name)
    {
        if (_systemClasses == null)
            loadSystemClasses();
        
        return _systemClasses.match(name);
    }

这里它没有使用tomcat那样多重的继承关系,哪些class是system的,哪些是server的,都是可以自己定义的

 public void addSystemClass(String classname)

也可以通过配置文件来定义。

 

通过上面的代码可以看到,一个类被判断为systemclass时,就会委托给系统类加载器,如果是serverclass,就一定会勇webxppClassLoader加载,由于WEB-INF/lib中并没有org.jetty.类,而且由于以下的代码,保证server类不会委托给系统类加载器,所以如果WEB-INF/lib没有,就会报ClassnotFound,从而达到了容器类对于应用不可见的目的。

(测试时,可以在pom中引入jetty的容器类,但定义为provided,或者直接用class.forname之类的方式来测)


 

<think>好的,用户遇到了JettyWebAppContext启动失败的问题,需要排查原因。首先,我需要分析用户提供的引用内容,看看可能的问题点在哪里。 用户提供的引用中有四个错误信息。引用[1]和[2]提到了ClassNotFoundException,找不到WebAppContext和Connector类,这可能是因为依赖缺失或版本不兼容。引用[3]指出端口被占用,导致Jetty无法启动。引用[4]提到了文件找不到,可能是web.xml配置错误或者资源路径不正确。 接下来,我需要按照步骤逐一分析可能的原因。首先检查依赖配置,确保所有Jetty相关的库正确引入,版本是否一致。然后查看端口占用情况,使用netstat或者lsof命令确认端口是否被其他进程占用。接着检查web.xml的配置,是否存在语法错误或路径错误。资源路径方面,确认webapp目录结构是否符合Jetty的要求,特别是WEB-INF的位置是否正确。日志信息需要用户提供更多的细节,比如堆栈跟踪,以便定位异常发生的具体位置。 此外,用户提供的错误信息中有多个不同的异常,可能需要综合考虑。例如,ClassNotFoundException可能和依赖管理工具(如Maven或Gradle)的配置有关,需要检查pom.xml或build.gradle文件中的依赖项是否正确。端口被占用的问题可能需要更改端口号或终止占用端口的进程。文件找不到的问题则需要验证资源路径是否正确,或者是否存在文件权限问题。 最后,生成相关问题时要覆盖依赖、端口、配置、资源路径和日志分析等方面,帮助用户全面排查可能的问题点。</think>### Jetty WebAppContext启动失败排查步骤 #### 1. 检查依赖配置 - 确认项目中包含完整的Jetty依赖链,特别是`jetty-webapp`组件(版本需与`jetty-maven-plugin`一致) ```xml <!-- Maven示例 --> <dependency> <groupId>org.mortbay.jetty</groupId> <artifactId>jetty-webapp</artifactId> <version>8.1.12.v20130726</version> </dependency> ``` 若出现`java.lang.ClassNotFoundException: org.mortbay.jetty.webapp.WebAppContext`,说明存在依赖缺失或版本冲突[^1][^2] #### 2. 检查端口占用 - 使用命令`netstat -ano | findstr 8080`(Windows)或`lsof -i :8080`(Linux/Mac)验证端口状态 - 修改端口配置: ```xml <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <configuration> <stopPort>9966</stopPort> <stopKey>stop</stopKey> <connectors> <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector"> <port>8090</port> <!-- 修改此处 --> </connector> </connectors> </configuration> </plugin> ``` 地址被占用错误可通过修改端口解决[^3] #### 3. 验证web.xml配置 - 检查`WEB-INF/web.xml`文件是否存在且路径正确 - 确认Servlet配置符合规范: ```xml <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> </web-app> ``` 文件路径错误会导致`java.io.FileNotFoundException`[^4] #### 4. 检查资源路径 - 确认webapp目录结构符合标准: ``` src └── main ├── resources └── webapp ├── WEB-INF │ └── web.xml └── index.jsp ``` - 验证静态资源引用路径是否正确(如CSS/JS文件路径) #### 5. 分析启动日志 - 添加`-X`参数获取详细日志:`mvn jetty:run -X` - 重点关注以下日志段: ``` [INFO] Starting scanner at interval of 1 seconds. [INFO] Starting Jetty Server... [INFO] jetty-8.1.12.v20130726 [INFO] No Transaction manager found - if your webapp requires one, please configure one. ``` 异常堆栈会在此区域显示具体错误位置
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值