通过上一节我们完成了对容器进行了加载、初始化、启动,而对于应用的加载部分独立出来,本节进行单独的讲解
 

一、应用加载流程

1)应用识别,Context创建

  • 在Host启动后,会调用Host的监听HostConfig进行启动事件处理
  • HostConfig在监听到启动事件后,会分别尝试从context.xml下,wabapps下war,webapp下文件夹进行应用的读取,读取过程中通过Host的启停线程池(startStopExecutor)进行独立线程读取,读取最终结果生成Context对象并添加进入Host容器中。注意这里用到了Future<?>协同方式
  • 这里构建的Context仅包含如下基本参数(如:name,path,webappVersion,docBase),另外会给Context默认增加监听ContextConfig
 

2)应用加载,Context启动

    • Engine启动ContainerBackgroundProcessor线程进行对所有容器进行后台处理,即调用所有容器的backgroundProcess()方法
    • 容器backgroundProcess()方法处理完成后,通知相应的监听器(事件类型为Lifecycle.PERIODIC_EVENT)
    • HostConfig会根据Context是否启动,进行相应启动操作(context.start()),
    • Context启动过程如下:
      • 获取一个WebAppLoader,
      • 应用类加载,执行WebAppLoader.start()方法,该方法内,会创建一个ClassLoader(WebappClassLoader),在调用ClassLoader.start()方法进行jar与class的加载
      • 添加应用级监听器至Context成员变量中,其中主要有:ServletContextAttributeListener,ServletRequestAttributeListener,ServletRequestListener,HttpSessionIdListener,HttpSessionAttributeListener,ServletContextListener,Context成员变量声明如下:
        private List<Object> applicationEventListenersList = new CopyOnWriteArrayList<>();
      • 执行SevletContextListener监听器上下文完成初始化方法(注意,Spring就是这里进行的初始化的)
    • Context启动完成后,通知相应的监听器ContextConfig,进行启动完成处理
    • ContextConfig.start()方法(核心为调用webConfig()方法)
      • 读取/WEB-INF/web.xml文件,构建WebXml对象
      • 解析所有class,判断是否有使用servlet相关注解(Ljavax/servlet/annotation/WebServlet),如果使用就注解对象手动添加至WebXml对象中,即生成ServletDef定义文件
      • 将jsp转换为ServletDef定义文件,并添加至WebXml对象中
      • 将WebXml对象内容解析至Context对象中(方法:configcontext),一个Servlet对应一个Wrapper容器

        for (Entry<String, String> entry : webxml.getContextParams().entrySet()) {
context.addParameter(entry.getKey(), entry.getValue());
}//context全局参数
....
for (ErrorPage errorPage : webxml.getErrorPages().values()) {
context.addErrorPage(errorPage);
}//404页面
for (FilterDef filter : webxml.getFilters().values()) {
if (filter.getAsyncSupported() == null) {
filter.setAsyncSupported("false");
}
context.addFilterDef(filter);
}//拦截器
for (FilterMap filterMap : webxml.getFilterMappings()) {
context.addFilterMap(filterMap);
}//拦截器Map
context.setJspConfigDescriptor(webxml.getJspConfigDescriptor());
for (String listener : webxml.getListeners()) {
context.addApplicationListener(listener);
}//监听器
......
for (ServletDef servlet : webxml.getServlets().values()) {
Wrapper wrapper = context.createWrapper();//一个servlet对应一个封装器Wrapper
// Description is ignored
// Display name is ignored
// Icons are ignored
// jsp-file gets passed to the JSP Servlet as an init-param
if (servlet.getLoadOnStartup() != null) {
wrapper.setLoadOnStartup(servlet.getLoadOnStartup().intValue());
}
if (servlet.getEnabled() != null) {
wrapper.setEnabled(servlet.getEnabled().booleanValue());
}
wrapper.setName(servlet.getServletName());
Map<String,String> params = servlet.getParameterMap();
for (Entry<String, String> entry : params.entrySet()) {
wrapper.addInitParameter(entry.getKey(), entry.getValue());
}
wrapper.setRunAs(servlet.getRunAs());
Set<SecurityRoleRef> roleRefs = servlet.getSecurityRoleRefs();
for (SecurityRoleRef roleRef : roleRefs) {
wrapper.addSecurityReference(
roleRef.getName(), roleRef.getLink());
}
wrapper.setServletClass(servlet.getServletClass());
MultipartDef multipartdef = servlet.getMultipartDef();
if (multipartdef != null) {
if (multipartdef.getMaxFileSize() != null &&
multipartdef.getMaxRequestSize()!= null &&
multipartdef.getFileSizeThreshold() != null) {
wrapper.setMultipartConfigElement(new MultipartConfigElement(
multipartdef.getLocation(),
Long.parseLong(multipartdef.getMaxFileSize()),
Long.parseLong(multipartdef.getMaxRequestSize()),
Integer.parseInt(
multipartdef.getFileSizeThreshold())));
} else {
wrapper.setMultipartConfigElement(new MultipartConfigElement(
multipartdef.getLocation()));
}
}
if (servlet.getAsyncSupported() != null) {
wrapper.setAsyncSupported(
servlet.getAsyncSupported().booleanValue());
}
wrapper.setOverridable(servlet.isOverridable());
context.addChild(wrapper);
}
for (Entry<String, String> entry :
webxml.getServletMappings().entrySet()) {
context.addServletMapping(entry.getKey(), entry.getValue());
}
//sesseionConfig对象
SessionConfig sessionConfig = webxml.getSessionConfig();
if (sessionConfig != null) {
if (sessionConfig.getSessionTimeout() != null) {
context.setSessionTimeout(
sessionConfig.getSessionTimeout().intValue());
}
SessionCookieConfig scc =
context.getServletContext().getSessionCookieConfig();
scc.setName(sessionConfig.getCookieName());
scc.setDomain(sessionConfig.getCookieDomain());
scc.setPath(sessionConfig.getCookiePath());
scc.setComment(sessionConfig.getCookieComment());
if (sessionConfig.getCookieHttpOnly() != null) {
scc.setHttpOnly(sessionConfig.getCookieHttpOnly().booleanValue());
}
if (sessionConfig.getCookieSecure() != null) {
scc.setSecure(sessionConfig.getCookieSecure().booleanValue());
}
if (sessionConfig.getCookieMaxAge() != null) {
scc.setMaxAge(sessionConfig.getCookieMaxAge().intValue());
}
if (sessionConfig.getSessionTrackingModes().size() > 0) {
context.getServletContext().setSessionTrackingModes(
sessionConfig.getSessionTrackingModes());
}
}
    • 从WebApp加载中读取ServletContainerInitializer的实现,并添加至context容器中
 
    至此,host下面的context,wrapper,等容器就就已经生成并初始化了。

最新文章

  1. 【前端性能】高性能滚动 scroll 及页面渲染优化
  2. 跟着百度学PHP[4]OOP面对对象编程-12-抽象类
  3. 去掉hive字段中的tab
  4. org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter与org.apache.struts.dispatcher.FilterDispatcher是什么区别?
  5. c语言 数组名是常量指针
  6. javascript优化--06模式(对象)01
  7. jquery的jquery c.browser msie undefined的问题解决办法
  8. Tkinter教程之Canvas篇(3)
  9. C++ 文件读写方案选型
  10. PIL(Python Image Library)生成验证码
  11. Oracle DB 自动管理共享内存
  12. Windows进程
  13. BZOJ 1416: [NOI2006]神奇的口袋( 高精度 )
  14. 【Bootstrap】 一些提示信息插件
  15. Mybatis源码分析之存储过程调用
  16. Dubbo的异常处理
  17. JAVA垃圾回收机制概要
  18. 解决:对COM 组件的调用返回了错误 HRESULT E_FAIL
  19. 【UOJ244】[UER7]短路
  20. 机器学习中的范数规则化之 L0、L1与L2范数、核范数与规则项参数选择

热门文章

  1. 使用moy快速开发后台管理系统(一)
  2. 简单聊聊HTTP/TCP/IP协议
  3. 深入理解 JavaScript 异步系列(2)—— jquery的解决方案
  4. 本人开发的JavaWeb急速框架Blast上线了
  5. 1688: [Usaco2005 Open]Disease Manangement 疾病管理
  6. SQL-with as基本用法(源码DEMO)
  7. Xamarin自定义布局系列——ListView的一个自定义实现ItemsControl(横向列表)
  8. RSA密码体制
  9. QQ好友在线/离线,怎么测试?
  10. 获取 metadata 的完整例子 - 每天5分钟玩转 OpenStack(166)