jetty学习2-WebAppContext

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方法又包括如下步骤:
    [java]  view plain copy
    1.   preConfigure();  
    2. super.doStart();  
    3. 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定位和加载。还有几个在此就不详述了。
    [java]  view plain copy
    1.  loadConfigurations();  
    2.   
    3. // Setup system classes  
    4. loadSystemClasses();  
    5.   
    6. // Setup server classes  
    7. loadServerClasses();  
    8.   
    9. // Configure classloader  
    10. _ownClassLoader=false;  
    11. if (getClassLoader()==null)  
    12. {  
    13.     WebAppClassLoader classLoader = new WebAppClassLoader(this);  
    14.     setClassLoader(classLoader);  
    15.     _ownClassLoader=true;  
    16. }  
    17.   
    18. if (Log.isDebugEnabled())  
    19. {  
    20.     ClassLoader loader = getClassLoader();  
    21.     Log.debug("Thread Context class loader is: " + loader);  
    22.     loader=loader.getParent();  
    23.     while(loader!=null)  
    24.     {  
    25.         Log.debug("Parent class loader is: " + loader);  
    26.         loader=loader.getParent();  
    27.     }  
    28. }  
    29.   
    30. // Prepare for configuration       
    31. for (int i=0;i<_configurations.length;i++)  
    32.     _configurations[i].preConfigure(this);  
  4. start方法先将classloader设置到线程上下文加载器,然后调用startContext,分为以下3个步骤
[java]  view plain copy
  1. protected void startContext()  
  2.        throws Exception  
  3.    {  
  4.        configure();  
  5.          
  6.        //resolve the metadata  
  7.        _metadata.resolve(this);  
  8.          
  9.        super.startContext();  
  10.    }  
  • 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来加载,核心代码如下:

[java]  view plain copy
  1. @Override  
  2.    protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException  
  3.    {  
  4.        Class<?> c= findLoadedClass(name);  
  5.        ClassNotFoundException ex= null;  
  6.        boolean tried_parent= false;  
  7.          
  8.        boolean system_class=_context.isSystemClass(name);  
  9.        boolean server_class=_context.isServerClass(name);  
  10.          
  11.        if (system_class && server_class)  
  12.        {  
  13.            return null;  
  14.        }  
  15.          
  16.        if (c == null && _parent!=null && (_context.isParentLoaderPriority() || system_class) && !server_class)  
  17.        {  
  18.            tried_parent= true;  
  19.            try  
  20.            {  
  21.                c= _parent.loadClass(name);  
  22.                if (Log.isDebugEnabled())  
  23.                    Log.debug("loaded " + c);  
  24.            }  
  25.            catch (ClassNotFoundException e)  
  26.            {  
  27.                ex= e;  
  28.            }  
  29.        }  
  30.   
  31.        if (c == null)  
  32.        {  
  33.            try  
  34.            {  
  35.                c= this.findClass(name);  
  36.            }  
  37.            catch (ClassNotFoundException e)  
  38.            {  
  39.                ex= e;  
  40.            }  
  41.        }  
  42.   
  43.        if (c == null && _parent!=null && !tried_parent && !server_class )  
  44.            c= _parent.loadClass(name);  
  45.   
  46.        if (c == null)  
  47.            throw ex;  
  48.   
  49.        if (resolve)  
  50.            resolveClass(c);  
  51.   
  52.        if (Log.isDebugEnabled())  
  53.            Log.debug("loaded " + c+ " from "+c.getClassLoader());  
  54.          
  55.        return c;  
  56.    }  

 

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

[java]  view plain copy
  1. public boolean isSystemClass(String name)  
  2. {  
  3.     if (_systemClasses == null)  
  4.         loadSystemClasses();  
  5.       
  6.     return _systemClasses.match(name);  
  7. }  

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

[java]  view plain copy
  1. public void addSystemClass(String classname)  

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

 

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值