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。还有一个原因就是,这一部署方法在本地部署和远程部署中都能生效。