WEB应用是怎么被部署的,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
一个WEB应用,无论是解压后的目录,还是一个压缩的WAR文件,都支持部署到应用服务器中。
一个WEB应用安装到应用服务器的过程,我们称为部署。
部署应用的形式又分多种:
静态的:即应用服务器启动时就存在在Server中的应用。
动态的:即应用服务器运行时动态的把应用添加应用服务器中,支持应用的请求。
动态部署的实现在Tomcat中可以通过其自动部署特性来完成。
也可以通过Tomcat的Manager应用来实现远程部署。
我们今天先来看一下Tomcat的自动部署实现原理。
整个HostConfig中涉及到多种类型的部署
自动部署的时候,我们常规操作是直接把一个标准WAR应用放到
%Tomcat_HOME%/webapps
目录下,而后台线程会定时扫描,发现有需要部署的应用,就会启动部署流程进行应用部署。对于后台线程,感兴趣的朋友可以看前面的文章:
对于过期的session,Tomcat做了什么?
后台线程发现了我们的应用后,会调用到
HostConfig
类中的
deployWar
方法。
由于Tomcat支持以context.xml这种提供xml配置格式的应用部署等,所以方法内有大量判断各类部署情况的逻辑。
最终,一个Web应用会对应到一个StandardContext
对象上,一个Web应用又会被部署到一个虚拟主机上。
最核心的逻辑是下面这几行:
Class<?> clazz = Class.forName(host.getConfigClass()); LifecycleListener listener = (LifecycleListener) clazz.newInstance(); context.addLifecycleListener(listener); context.setName(cn.getName()); context.setPath(cn.getPath()); context.setWebappVersion(cn.getVersion()); context.setDocBase(cn.getBaseName() + ".war"); host.addChild(context);
在设置完Context的属性后,将其添加到虚拟主机上⇒ host.addChild(context)
在·addChild·的逻辑中,主要是把这个应用启动起来
// Start child if ((getState().isAvailable() || LifecycleState.STARTING_PREP.equals(getState())) && startChildren) { try { child.start(); } catch (LifecycleException e) { log.error("ContainerBase.addChild: start: ", e); throw new IllegalStateException ("ContainerBase.addChild: start: " + e); } }
此处,启动内会处理许多事情,像Webapp的ClassLoader设置是否使用双亲委托,web.xml
和default web.xml
的merge,以及解析应用中是否包含web-fragement.xml
,将多项配置合并后,这项工作是在ContextConfig
类内完成的。
解析完web.xml后,会生成一个Webxml对象,需要根据具体的应用配置信息,初始化我们的组件了,例如Filter,Listener等,
例如下面的逻辑
private void configureContext(WebXml webxml) { for (FilterDef filter : webxml.getFilters().values()) { if (filter.getAsyncSupported() == null) { filter.setAsyncSupported("false"); } context.addFilterDef(filter); } for (FilterMap filterMap : webxml.getFilterMappings()) { context.addFilterMap(filterMap); } context.setJspConfigDescriptor(webxml.getJspConfigDescriptor()); for (String listener : webxml.getListeners()) { context.addApplicationListener(listener); } for (ServletDef servlet : webxml.getServlets().values()) { Wrapper wrapper = context.createWrapper(); wrapper.setOverridable(servlet.isOverridable()); context.addChild(wrapper); } }
整个解析出的Servlet组件,又会被做为Context的子组件添加到应用中。
在解析完Servlet等组件后,会再根据配置设置Session的超时时间,SessionCookie的名称等。对这一部分,可以看前面的文章:深入Tomcat源码分析Session到底是个啥!
一切都OK后,设置应用的配置状态
// Make our application available if no problems were encountered if (ok) { context.setConfigured(true); } else { log.error(sm.getString("contextConfig.unavailable")); context.setConfigured(false); }
再然后,就是对于filter
和listener
等组件的启动了。这些组件的启动是根据前一个组件是否启动成功,再决定是否继续
if (!getConfigured()) { log.error( "Error getConfigured"); ok = false; } // Configure and call application event listeners if (ok) { if (!listenerStart()) { log.error( "Error listenerStart"); ok = false; }
根据Servlet规范进行的容器实现,都是先进行listener的启动,再进行filter启动。可能某天面试时会有人问到,或者涉及到应用组件加载问题时,记的在这里看到过。
在组件等全部启动完毕后,整个应用部署就完成了。
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注亿速云行业资讯频道,感谢您对亿速云的支持。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。