JettY 部署Web应用程序.docx
《JettY 部署Web应用程序.docx》由会员分享,可在线阅读,更多相关《JettY 部署Web应用程序.docx(22页珍藏版)》请在冰豆网上搜索。
JettY部署Web应用程序
第5章部署Web应用程序
当我们编写好一个web应用程序,如何交付给Jetty容器来运行呢?
这也就是所谓“部署web应用程序”。
本章将介绍如何在Jetty中部署web应用,以及在Jetty的构架体系中是如何实现web应用部署的。
5.1常用术语
为了使本章中讨论的内容能得到大家一致的理解,本节先明确一些专业术语,避免大家造成误解。
web应用程序(WebApplication)
经常会说到这个词,大家也不难理解,就是由一组文件构成的集合,这些文件可能包含html文件、图像文件、java编译后的class文件,配置文件等等所有可能出现的文件。
符合Servlet规范的应用程序还要求目录下存在一个WEB-INF的文件夹,在里面还必须存在一个web.xml的web部署配置文件,关于这个目录和web.xml的内容格式都是Servlet规范中定义的。
根据Servlet规范我们还可以web应用程序整个目录打包成war文件。
上下文(Context)
上下文是我们经常听到的词汇,可以使用在各种专业场合,但当我谈论web应用程序的时候,是这样的意思。
首先看一个名为Example的web应用程序的访问URL,/index.jsp。
可以发现要访问这个Example应用,所有的路径都需要加前缀“/example”,换句话说,就是该应该的访问地址都符合这种模式。
所有已
这就是上下文的概念了。
有了上下文的概念后,一个web服务下就可以部署多套不同的web应用程序了,且不同的应用程序不会造成混乱。
上下文路径(ContextPath)
在术语上下文的中,我们举例的“/example”就是上下文路径。
同一个服务器下的不同的web应用就应该有不同的上下文路径。
注意:
上下文路径必须以“/”开头,且不能以“/”结尾。
在Servlet规范中,通过API,request.getContextPath()方法来获取当前应用程序的上下文路径
5.2初探
如果你使用过Tomcat服务器的话,那么你一定知道在Tomcat下部署一个web应用会有两种方式:
一、将web程序目录或者war文件程序复制到webapps目录。
二、编写配置文件,指向到web程序的目录。
我们Jetty也提供类似这两种方式,确有略为不同。
静态部署
在jetty安装目录下存在一个名为webapps的目录,你可以存放web应用程序或者war文件。
Jetty服务启动时会扫描webapps目录下面的文件,如果识别为web应用程序,那么就启动它。
上下文路径就是文件夹的名称或者war文件的名称。
(文件夹或war的名称是root,对应的上下文路径为“/”)
此类部署方式之所以被称为静态部署,是因为在服务器启动完成后便不在扫描webapps目录变动情况了,换句话说,在服务启动完成后,再在webapps部署新的web应用,不会及时生效,需等到服务器重启后才能被识别。
顺便提醒下,虽然这里叫静态部署,但是web应用里面的jsp被修好后,还是会被动态重编译。
动态部署
在jetty安装目录下存在一个名为contexts的目录,在这个目录里面是用来放置动态部署的配置文件的,配置文件是xml文件,使用的语法和第4章介绍的JettyxmlConfiguration语法相同。
(配置文件语法统一,这也是jetty设计优秀之处)jetty启动服务时,会开启一个线程每隔一段时间扫描contexts目录下的xml配置文件,然后更加配置文件的内容来部署一个web应用。
当服务器启动后的任意时刻,你在contexts下新增一个配置文件,jetty就会动态地启动这个web应用,同理,删除一个已存在的配置文件,jetty就会关闭相应的web应用。
你也可以修改一下配置文件的最后修改时间,来达到重启web应用的功能。
此类部署方式就是所谓的动态部署了。
需要提醒的是,通常情况下你会认为部署一个web应用程序,那么这个web应用一定是符合Servlet规范的,不然jetty为什么会叫servlet容器呢!
但是Jetty的设计哲学没有强迫你非得这样做,Jetty允许你发布一个支持上下文功能,但不支持Servlet的应用。
如,在jetty自带的示例中,contexts目录下有一个文件javadoc.xml,内容如下:
xmlversion="1.0" encoding="ISO-8859-1"?
>
DOCTYPEConfigurePUBLIC"-//MortBayConsulting//DTDConfigure//EN""http:
//jetty.mortbay.org/configure.dtd">
--
Configureacustomcontextforthejavadoc.
ThiscontextcontainsonlyaServletHandlerwithadefaultservlet
toservestatichtmlfilesandimages.
-->
Configurejavadoc.xml
/javadoc
/javadoc/
- index.html
- contents.html
--theindexifjavadocnotgenerated-->
max-age=3600,public
该配置文件启动了一个java文档的web服务,文档的静态文件被放在$jetty_home/javadoc目录下,访问地址是http:
//127.0.0.1:
8080/javadoc。
现在看不懂这个文件也不要紧,后续内容会设计,这里只是用来展示下Jetty的灵活性。
webapps目录和contexts目录
这两个目录的位置一定必须在jetty安装目录下面么?
它们的名字必须如此么?
根据前面不断宣称的Jetty的灵活性,答案肯定是否定的。
目录的名称和位置只是jetty.xml文件中的默认配置,如果你愿意都可以修改。
5.3Jetty实现上下文功能的基本原理
既然jetty可以同时部署多个web应用程序,那么必然支持上下文功能。
本小节向你展示下Jetty是如何支持上下文功能。
在默认的服务配置文件jetty.xml中有如下一段配置:
--===========================================================-->
-- 设置Handlers-->
--===========================================================-->
-- HandlerCollection中每一个Handler都会被按顺序执行 -->
-- ContextHandler的集合 -->
-- DefaultHandler如果前一Handler没有处理request的话就会执行它。
用来输出提 示信息或者输出网站图标 -->
-- 请求日志记录器 -->
通过这段默认配置,为Jetty的Server对象设置了一组Handler对象,结构如下图:
Server对象将接收到的HTTP请求转发到HandlerCollection对象,再由HandlerCollection对象将HTTP请求按顺序转发给内部所有的Handler对象,即被HandlerCollection包含的对象都有机会去处理每一个请求。
让我们看一段HandlerCollection的核心代码,来验证上面的说法:
for(inti=0;i<_handlers.length;i++)
{
try
{
_handlers[i].handle(target,request,response,dispatch);
}
catch(IOExceptione)
{
throwe;
}
catch(RuntimeExceptione)
{
throwe;
}
catch(Exceptione)
{
if(mex==null)
mex=newMultiException();
mex.add(e);
}
}
现在来主要看本节的主角ContextHandlerCollection,通过
来配置,从上图中看出它也是一个集合,集合就意味着可以容纳其他Handler,再从类名可以看出该集合只能容纳ContextHandler类以及它的子类。
New标签的id属性被设置为“Contexts”,由第4章的内容可知ContextHandlerCollection对象会以key为“Contexts”保存起来,可以使用Ref标签可以再次引用该对象,如何引用在下面的篇章会介绍。
ContextHandlerCollection的作用是什么?
其作用是将接收到的请求分发给正确的ContextHandler来处理,分发的依据就是ContextHandler的上下文路径。
5.3静态部署的原理和配置文件
上一节介绍了ContextHandlerCollection对象,但何时、如何向该对象中放入ContextHandler对象或其子类对象呢?
本节介绍的静态部署将是其中的一种方法。
先看一段jetty.xml中的配置片段:
--===========================================================-->
--Configurethewebappdeployer. -->
--Awebapp deployerwilldeploystandardwebappsdiscovered -->
--inadirectoryatstartup,withouttheneedforadditional -->
--configurationfiles. Itdoesnotsupporthotdeployor -->
--nonstandardcontexts(seeContextDeployerabove). -->
-- -->
--Thisdeployerisconfiguredtodeploywebappsfromthe -->
--$JETTY_HOME/webappsdirectory -->
-- -->
--Normallyonlyonetypeofdeployerneedbeused. -->
-- -->
--===========================================================-->
/webapps
false
true
false
/etc/webdefault.xml
等价的Java代码是:
WebAppDeployerwebAppDeployer=newWebAppDeployer();
webAppDeployer.setContexts(env.get("Contexts"));
webAppDeployer.setWebAppDir(System.getProperty("jetty.home",".")+"/webapps");
webAppDeployer.setParentLoaderPriority(false);
webAppDeployer.setExtract(true);
webAppDeployer.setAllowDuplicates(false);
webAppDeployer.setDefaultsDescriptor(System.getProperty("jetty.home",".")+"/etc/webdefault.xml");
server.addLifeCycle(webAppDeployer);
其实Jetty就是用WebAppDeployer对象来完成静态部署的任务的。
上一节中我们说过ContextHandlerCollection对象会以key为“Contexts”保存起来,WebAppDeployer.setContexts(env.get("Contexts"));方法将ContextHandlerCollection对象的引用设置给了webAppDeployer对象,在服务器启动过程中WebAppDeployer将默认实例化一些的ContextHandler的子类WebappContext的实例,并添加到ContextHandlerCollection对象中去。
大致的过程就是这样的,细节问题接下来会讨论。
WebAppDeployer类的工作内容
当服务器启动时,WebAppDeployer扫描指定的WebAppDir目录(默认配置为System.getProperty("jetty.home",".")+"/webapps",及jetty安装目录下的webapps目录,可以修改)。
在WebAppDir目录中发现的文件夹或者.war文件或者.jar文件,每个文件夹或文件都会被看作是一个的web应用程序,实例化一个WebAppContext对象,并将该对象添加到ContextHandlerCollection对象中去。
WebAppContext代表一个支持Servlet标准的应用程序。
5.4动态部署的原理和配置
动态部署的原理和静态部署基本原理差不多,都是向ContextHandlerCollection对象中增加ContextHandler的实例对象。
先看一段jetty.xml的配置:
--===========================================================-->
--Configurethecontextdeployer -->
--Acontextdeployerwilldeploycontextsdescribedin -->
--configurationfilesdiscoveredinadirectory. -->
--Theconfigurationdirectorycanbescannedforhot -->
--deploymentsattheconfiguredscanInterval. -->
-- -->
--Thisdeployerisconfiguredtodeploycontextsconfigured -->
--inthe$JETTY_HOME/contextsdirectory -->
-- -->
--===========================================================-->
/contexts
5
等价的Java代码是:
ContextDeployercontextDeployer=newContextD