Apache Ant自动化部署
如果要周期性地改变Web应用程序,并不得不经常执行这些不同的部署步骤,则会想要让过程自动化,而非每次都要重新输入jar(或许还有copy/cp)命令。本节会教您如何使用Ant。这是Apache Software Foundation (Apache软件基金会)的构建(build)工具。您也可以使用任何喜爱的工具——诸如make, Perl, shell脚本或批处理文件。不过,在Java与Tomcat社区中,Ant已渐渐成为自动部署的标准工具,所以最妤能对Ant有基础的认识。
Ant会自动执行其他的程序,更精确地说,Ant可以运行非Java程序。它可以执行非Java的程序,不过仅只是执行Java类,就因能处理许多事情而获益。因为Ant是以Java编写的,而且有可靠的JVM,因此执行其他的Java功能(包括Java编译器)会相当快速,因为JVM已相当盛行。Ant也含有执行一般操作的内嵌任务的庞大链接库,包括处理TAR,JAR,ZIP,GZIP及其他文件格式,而且通常不諸执行外部程序。也就是说,它含有能读/写 这些及其他格式文件、复制文件和编译Java程序(包括servkt)等的OS便携式Java类。
Ant会读入以XML编写的构建(build)文件,以找寻要执行的命令,而一般的文件名则为build.xml。Ant的构建文件包含一个项目定义,以及许多目标(target;类似于子程序),其中一个是默认的目标。目标是一个类似于如何处理下列事情的工作单位, 编译某些servlet、构建JAR文件或复制JAR文件。在Ani的命令上,您可以用名字执行任何目标,如果不提供目标名称,则默认目标是run。每个目标都可以包含任务,而任务初略地类似于单独的命令。
构建 JAR/WAR
Ant有处理JAR/WAR文件,及复制文件的嵌人式任务。示例3-2是Web应用程序中的一个build.xml示例,只是在用干此处时作了一些轻微的裁减。
示例3-2:可产生WAR文件的Ant构建文件(build.xml)
<project name="Hello World Web Site"
default="war
basedir=".">
<!—构建WAR文件-->
<target name="war"
description="Builds the WAR file.">
<war destfile="${deploy.war}"
webxml="${basedir}/Webapp-dir/WEB-INF/web.xml"
basedir="${basedir}/webapp-dir"
excludes="WEB-INF/**/*">
<lib dir="${basedir}/webapp-dir/WEB-INF/lib"/>
<webinf dir="${basedir}/webapp-dir/WEB-INF"
excludes="web.xml"/>
<metainf dir="${basedir}/webapp-dir/META-lNF"/>
</war>
</target>
</project>请注意war Ant任务怎样创建WAR文件。笔者在打包文件中使用了webxml属性,并给合提供WEB-INF/web.xml文件的路径,然后让它包含了Web应用程序的basedir下的所有文件,并设置为${basedir}/webapp-dir。笔者还告诉Ant,在哪里能找到这个特殊对待的WEB-INF目录,这个目录很特殊,它虽然没有包含服务于客户端的文件,但仍 然组成了Web应用程序代码和配置文件。但是,笔者不想在该打包文件中再包含WEB-INF/web.xml因为这会让Ant误认为笔者想两次包含web.xml。因此,笔者进行了excludes="WEB-INF/**/*"属性设置。双星号(**)意味着映射所有目录路径,由此推断,这一设置排斥了属性设置并让Ant不包含WEB-INF树中的内容。这是笔者预期的内 容,因为webinf元素巳经包含了减去web.xml/文件(这已通过webxml属性 进行了特殊处理)。
通过Ant进行部署
通过ANT编译工具部属Web应用程序的方法有多种:
复制Web应用程序到本地Tomcat安装的部署目录中
只复制Web应用程序的解包目录或WAR文件到已配置好的Tomcat Host appBase目录(如CATALINA_HOME/webapp)下,然后根据已配置的Host,有选择地重启Tomcat。这是Ant可轻松完成的事情,只要执行一个<copy>。
使用Manag以Web应用程序,通过网络^远程”部署Web应用程序
Ant可以通过HTTP使您与Manager Web应用程序交互。Tomcat提供的定制Ant任务,给您与Tomcat的Manager Web应用程序提供了一个很好的可编程Ant接口。如果Tomcat与Ant运行在同一台机器上,则可以实现本地化,如果Tomcat与Ant运行 在不同的机器上,则可以实现远程化。无论是哪种方式,Ant都使用了网络,通过 HTTP给Tomcat发送命令。
使用Tomcat的独立部署器
Tomcat有一个独立部署器,它实际是一个目录,该目录包含了通过HTTP给 Manager Web应用程序提供命令的Ant编泽工具和所有必要的JAR文件。
使用Ant的scp(Secure CoPy)任务 Ant能在网络上通过scp Ant任务远程复制文件。您需要完成的任务只是增加一个启用scp让任务的JAR文件,然后编写一个该任务使用的Ant编译文件。这一方法可用于远程或本地安装的Tomcat,只要远程复制的目的机器正运行了一个非Windows操作 系统上都有的SSH (Secure SHell)后台程序就可以了。
复制WAR文件或Web应用程序目录
通过Ant进行部署的最简便的方法足Tomcat与Ant正运行在同一台机器上的情况,一旦已经建立Web应用程序,您就可以编写在网络上复制Web应用程序到Tomcat中的编译文件 记住:不要仅复制Web应用程序,而不为您正处理的事情配置Tomcau在本章前面, 笔者复习了Tomcat支持的各种部署方法及存在的问题。您大概想复制Web应用程序和 context XML片段文件,这要依您要将Web应用程序映射的URI和如何配置Host而定。 示例3-3是示例3-2编译文件的扩展版本,但这-版本也把文件复制到Tomcat的部署目录中。
示例3-3:编译和部署WAR文件的Ant脚本
<project name=nHello World Web Site"
default="war"
basedir=".">
<!--在此处存储"常量"便于修改-->
<property name="deploy.dir"
value=/opt/tomcat/webapps"/>
<propeity name="deploy.war" value=/tmp/hello.war"/>
<!--编译WAR文件-->
<target name="war"
description="Builds the WAR file.">
<war destfile=${deploy.war}"
webxml = "${ basedir}/webapp-dir/WEB-INF/web.xml"
basedir="${basedir}/webapp-dir"
excludes="WEB-lNF/**/*">
<lib dir="${basedir}/webapp-dir/WEB-INF/lib"/>
<webinf dir="${basedir}/webapp-dir/WEB-INF"
excludes="web.xml"/>
<metainf dir="${basedir}/webapp-dir/META-INF"/>
</war>
</target>
<!--复制WAR到Toncat的部署目录中-->
<target name="deploy" depends="war"
description="Deploys the WAR file locally.">
<copy file="${deploy,war}" todir="${deploy.dir}"/>
</target>
</project>如果运行版本2,则它以相同方式产生WAR文件。然后可以测试这个WAR文件(使用命令行解包工具)。然后,重新调用Ant,对Web应用稈序进行本地部署。整个会话过程展现在示例3-4中。
示例3-4:使用Ant编译和部署该WAR文件
ian$ ant Buildfile:build.xml [jar] Building jar: /tmp/hello.war BUILD SUCCESSFUL Total time: 2 seconds ian$ $ unzip -t /tmp/hello.war Archive: /tmp/hello.war testing: meta-inf/ OK testing: META-INF/MANIFEST.MF OK testing: WEB-INF/ OK testing: WEB-INF/classes/ OK testing: /upload/image/course/tomcat/ OK testing: WEB-INF/web.xml OK testing: index.jsp OK testing:/upload/image/course/tomcat/logo.png OK testing: build.xml OK testing: ListParametersForm.html OK testing: play.html OK testing: jspIncludeCGI.jsp OK 在压缩的数据包/tmp/hello.war中没检测到错误。 ian$ sudo ant deploy Buildfile: build.xml war: deploy: [copy] Copying 1 file to /opt/tomcat/webapps BUILD SUCCESSFUL Total time: 2 seconds ian$
访问Manager Web应用程序
Manager Web应用程序的所有任务都可以通过Ant进行自动访问。
因为这些Ant任务实际使用了Manager Web应用程序,所以必须提前设置好一个用户名与口令,组合在Tomcat领域中,并允许成为管理员角色。
然后,需要更新Ant的build.xml文件,以提供从任务名到Java类的映射,实现Tomcat的Ant任务,您可以将这Ant配置增加到build.xml文件中。表3-1列出了Tomcat的Catalina Ant任务。
表3-1: Tomcat Catalina Ant任务
| 任务名 | Java类名 | 描述 |
|---|---|---|
| deploy | org.apache.catalina.ant.DeployTask | 部署Web应用程序 |
| list | org.apache.catalina.ant.ListTask | 列出当前部署的所有Web应用程序 |
| reload | org.apache.catalina.ant.ReloadTask | 重新加载Web应用程序 |
| sessions | org.apache.catalina.ant.SessionsTask | 列出给定的Web应用程序的所有现行会话 |
| resources | org.apache.catalina.ant.ResourcesTask | 列出所有全局JNDI资源 |
| roles | org.apache.catalina.ant.RolesTask | 列出 Tomcat 的所有安全角色 |
| start | org.apache.catalina.ant.StartTask | 启动一个Web应用程序 |
| stop | org.apache.catalina.ant.StopTask | 停止一个 Web 应用程序 |
| undeploy | org.apache.catalina.ant.UndeployTask | 解除一个Web应用程序的部署 |
| validator | org.apache.catalina.ant.ValidatorTask | 使本地文件系统上的一个web.xml文件生效 |
| jmxset | org.apache.catalina.ant.JMXSetTask | 设置一个Tomcat Mbean的JMX属性值 |
| jmxset | org.apache.catalina.ant.JMXSetTask | 得到一个Tomcat Mbean的JMX属性值 |
| jmxquery | org.apache.catalina.ant.JMXQueryTask | 査询Tomcat Mbean |
示例3-5的build.xml文件可以构造该WAR文件,将它部署到Tomcat中(使用Tomcat的安 装任务),然后列出现行部署的所有Web应用程序(使用Tomcat的列表任务)。
示例3-5: build.xml使用Tomcat的 Ant任务
<project name="Hello World Webapp" default="war"
basedir=".">
<!--将该编译文件指向Tomcat安装目录-->
<property name=”catalina.home" value="/opt/tomcat"/>
<!--在只有自己设定的用户可以读的独立文件中存储用户名和口令-->
<property file="user-pass.properties"/>
<property name="deploy.dir"
value="/opt/tomcat/webapps"/>
<property name="deploy.war" values="/tmp/hello.war"/>
<!--设置context路径-->
(property name="path" value="/hello"/>
<!--访问Manager Web应用程序的属性-->
<property name="manager.url"
value=http://localhost:8080/manager"/>
<path id="tomcat.lib.classpath>
<fileset dir="${catalina.home}/bin">
<include name="*.jar"/>
</fileset>
<fileset dir="${catalina.home}/lib">
<include name="*.jar"/>
</fileset>
</path>
<!--给Manager Web应用程序紀置自定义任务-->
<taskdef
resource="org/apache/catalina/ant/catalina.tasks"
classpathref="tomcat.lib.classpath"/>
<!-- 编译war文件 -->
<target name="war">
<war destfile="${deploy.war}"
Webxml="${basedir}/webapp-dir/WEB-INF/web.xml"
basedir="${basedir}/webapp-dir"
excludes="WEB-INF/**/*">
<lib dir="${basedir}/webapp-dir/WEB-INF/lib"/>
<webinf dir="${basedir}/webapp-dir/WEB-INF"
excludes="web,xml"/>
<metainf dir="${basedir}/webapp-dir/META-INF"/>
</war>
</target>
<!--部署新的web应用程序-->
<target name="deploy" depends="war"
descriptions="Deploys the webapp.">
<deploy url="${manager.url}"
username="${user}"
password="${pass}"
path="${path}"
war="file://$ {deploy.war}"/>
</target>
<!--重载该web应用程序-->
<target name="reload" depends="war"
description="Reloads the webapp.">
<reload url="${manager.url}"
userrame="${user}"
password="${pass}"
path="${path}"/>
</target>
<!--获得所有web应用程序的状态-->
<target name="list"
description="Lists all running webapp."<
<list url="${manager.url}"
username="${user}"
password="${pass}"/>
</target>
<target name="clean"
desctiption="Cleans the builds.">
<delete file="${deploy.war}"/>
</target>
</project>文件是一个Java属性文件,所以笔者使用Ant的属性任务,在该文件中包含了一个文件属性。这使Ant读取该属性文件,然后在Ant JVM中设置该属性文件的 所有属性,从而使这些设置可用于编译。 出于安全防护需要,您如果坚持要在命令行上指定口令,而不是让它留在文件中,那么您可以在该文件中放置一个虚拟口令(或者完全省略),然后使用下列内容在运行时指定口令:
$ ant-Dpassword=deep_dark_secret deploy
为触发重载,尝试:
ian$ ant reload Buildfile: build.xml Mar: [jar] Building jar: /tmp/hello.war reload: [reload] OK - Reloaded application at context path /hello BUILD SUCCESSFUL Total time: 3 seconds
注意在完成这一工作时,Ant使用了网络连接到Tomcat的Web服务器,告泝Tomcat要重 新加载该Web应用程序。如果您已为Manager Web应用程序止确设置了用户名和口令, 且假设在Ant和Tomcat之间没有防火墙,则运行正常,否则会阻塞HTTP连接。
用这种方式修改Web应用程序的如文件,远程使用Manager Web应用程序,是笔者 建议您通过Ant部署Web应用程序的方法,即使您的Tomcat在同一台机器上,也是如此。 这是因为与只复制文件相比,Ant更能根据您控制的需要,以多种方式控制Tomcat。还有一个原因就是,这一部署方法在本地部署和远程部署中都能生效。