转载自ph0ly:http://www.ph0ly.com

一、WebAppContext的概念

WebAppContext是Jetty处理器中核心的Handler,集成了众多其他基础Handler,并提供标准的JavaEE类加载机制

二、应用场景

WebAppContext提供完善的Session、Servlet、Filter的处理逻辑,它可以帮助我们构建一个标准的J2EE Web服务

三、继承体系

Jetty9源码剖析 - Handler组件 - WebAppContext

可以看到WebAppContext是一个ServletContextHandler,同时实现了WebAppClassLoader.Context接口,完成系统类判断和控制类加载顺序

四、源码剖析

1 、WebAppContext的创建

Jetty9源码剖析 - Handler组件 - WebAppContext

构造函数重载比较多,我们看到options默认会包含SESSIONS和SECURITY,也就是默认会启用SessionHandler和SecurityHandler

可以看到作为一个传统的war形式的路径传入,WebAppContext也能解析

Jetty9源码剖析 - Handler组件 - WebAppContext

最终其他构造函数全部调用到这里,父类ServletContextHandler会先初始化,之后创建WebAppContext.Context,这个类其实就是在ServletContextHandler.Context基础之上扩展了一些Listener操作,这里就不在多说

然后就是异常处理器和保护路径,保护路径即Servlet规范要求的WEB-INF、META-INF目录了

2、WebAppContext的启动

Jetty9源码剖析 - Handler组件 - WebAppContext

前面是处理MetaData,这个类在HttpParser解析这块用的比较多,这里就不细说

主要来看preConfigure和postConfigure

Jetty9源码剖析 - Handler组件 - WebAppContext

第一步完成配置加载,主要是实例化默认的web-inf、web-xml、meta-inf等配置的类

第二步完成系统类加载,主要是初始化系统类名称,例如java、javax、org.xml、org.w3c等开头的包名或者具体的类

第三步完成服务端类加载,主要是初始化服务端类名称,例如org.eclipse.jetty开头的类(也有部分排除)

这里为什么会区分系统类、服务端类呢?待会儿我们一起来分析下WebAppClassLoader就明白了

如果这里没有设置过类加载器,则自动创建一个WebAppClassLoader

配置刚才的所有配置,调用了preConfigure,预配置

Jetty9源码剖析 - Handler组件 - WebAppContext

postConfigure比较简单,就是前面的configurations调用postConfigure,这里不多讲

3、WebAppClassLoader的实现

Jetty9源码剖析 - Handler组件 - WebAppContext

可以看到它是一个URLClassLoader,我们来看它最核心的方法loadClass

Jetty9源码剖析 - Handler组件 - WebAppContext

Jetty9源码剖析 - Handler组件 - WebAppContext

先来看下Servlet规范要求,摘自Jetty官网(http://www.eclipse.org/jetty/documentation/9.3.x/jetty-classloading.html)

Jetty9源码剖析 - Handler组件 - WebAppContext

1. 默认优先加载WEB-INF/lib、WEB-INF/classes,其次是父类加载器

2. 系统类如java.lang.String不需要webapp类加载器加载

3. 服务端类如Server类不应该对应用程序类加载器可见,即应用程序不应该去加载Web容器的类

======== 再回头看代码 =========

这里对同一名称的全类名类加锁,不言而喻,防止重复加载

首先是常规操作,是否加载过了,加载过就直接返回

然后就是根据是否以父类加载模式方式加载,即双亲委派模型加载(默认不是双亲委派模式)

如果是父类加载器优先:

首先调用父类加载器加载类,如果当前类不是服务端类,才返回,也就是说大部分jetty自有的类是不允许使用父类加载器

父类加载器未找到该类,则尝试webapp自身的加载方式加载

如果是应用类加载器优先:

如果不是系统类,则将类文件读入并定义类,加载完成

如果当前是系统类,例如java本身的类或者部分jetty自身实现的类,则会使用父类加载器加载,如果父类加载器仍然加载不到,会使用webapp自身加载方式尝试加载,加载不到就抛ClassNotFoundException

相信看完WebAppClassLoader后,大家应该清楚之前的systemClasses和serverClasses是干什么的了

顺便推荐一篇文章 血泪的Jetty ClassLoader

4、WebAppContext.startContext启动上下文

Jetty9源码剖析 - Handler组件 - WebAppContext

该方法在ContextHandler.doStart触发,这里首先configure,完成各配置的configure,由于不属于核心,这里不细讲

metadata元数据比较简单,读者可以自行下来查看

之后启动webapp,其实就是调用了ServletContextHandler.startContext

五、总结

WebAppContext作为Jetty核心Handler,是我们构建Jetty标准Web必选的处理器。对于Spring Boot会在创建Server后,再创建一个JettyEmbeddedWebAppContext(其实是一个WebAppContext),从而Spring Boot能基于Jetty构建一个完整的Web应用。至此Jetty常规的传统Handler已完成分析,当然还有很多细节,感兴趣的读者下来可以自己分析,同时欢迎留言交流。后期我会增加WebSocket、Http2协议的相关知识,欢迎继续关注~

相关文章:

  • 2022-01-17
  • 2021-05-15
  • 2021-12-25
  • 2021-11-25
  • 2021-08-27
  • 2022-01-09
  • 2021-04-03
  • 2021-08-18
猜你喜欢
  • 2021-06-30
  • 2021-05-07
  • 2021-05-07
  • 2021-08-01
  • 2021-04-29
  • 2021-09-29
  • 2021-05-02
相关资源
相似解决方案