既然已经有了WAR文件(或 CAB文件), 是时候转向Web应用程序开发的部署了。如果你工作的机器本身就是一台Web服务器,部署将简单到只是把.war文件拷贝到服务器的相应应用程序目录。例 8-2说明了这一点; 这个创建文件建立和拷贝了一个 .war文件到Tomcat的webapps 目录.当你(重)启动Tomcat,这个.war文件就会被自动释放到一个同名的文件夹下(省去了.war扩展名),同时这个Web应用程序也就准备好了,在这个例子中,其URL是[url]http://localhost:8080/app[/url] (如果你正在部署一个Servlet, URL将会反映出Servlet的包结构,例如[url]http://localhost:8080/org/antbook/ch08/app[/url]说明Serlet类的结构org.antbook.ch08.app.)。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

例 8-2. Tomcat部署的创建文件 (ch08/simple/build.xml)

 

 

<?xml version="1.0" encoding = "UTF-8"?> <project default="main" basedir=".">         <property name="src" location="source" />        <property name="wardir" location=        "c:/tomcat/jakarta-tomcat-5.0.19/webapps"/>         <property name="warfile" location="${wardir}/app.war"/>                 <target name="main" depends="war">                <echo message="Deploying the Web app...."/>         </target>                <target name="war" >        <war destfile="${warfile}" webxml="${src}/app.xml" basedir="${bin}" />         </target> </project>

 

 

你可以使用Ant的 ftp 任务(查看第4章)来远程地部署到一个Web服务器的基础目录下。

 

使用SCP来部署

 

另一种从Ant 1.6开始的有效部署方式是SCP,它把一个文件或者FileSet从一个运行SSH (译者注:指SSH daemon。Daemon- [计] Internet中用于邮件收发的后台程序) 的远程主机上拷贝 (或者拷贝到远程主机上)。这种方式是一种可选的方式,而且你需要把jsch.jar 放到Ant的lib目录下来使用 (你可以从以下地址得到jsch.jar: [url]http://www.jcraft.com/jsch/index.html[/url])。

用这种方式部署起来很方便。例如,下面是一个怎样把一个单独的文件部署到一台远程主机的例子 (任何的主机,除非你明确地设置trust的属性为yes或者true,否则它一定要在你的已知主机 (knownhosts) 列表中):

 

 

<scp file="Project.jar"   todir="user:password@antmegacorp.com:/home/steven/cgi-bin"/>

 

 

你可以明确的使用password属性来设置密码:

 

 

<scp file="Project.jar"         todir="[email]user@antmegacorp.com[/email]:/home/steven/cgi-bin""         password="password"/>

 

 

如何拷贝一个远程文件到本地机器:

 

 

<scp file="user:password@antmegacorp.com:/home/steven/cgi-bin/Project.jar"   todir="${archive}"/>

 

 

如何利用fileset来拷贝一组文件:

 

 

<scp todir="user:password@antmegacorp.com:   /home/steven/source">     <fileset dir="${src}">        <include name="**/*.java"/>    </fileset></scp>

 

 

例8-3给出了一个完整的利用scp方式来部署的构造文件。(它使用了远程主机的IP地址来代替了命名远程服务器。)

 

例 8-3. 利用scp (ch08/scp/build.xml)

 

 

<?xml version="1.0" ?><project default="main">     <property name="message" value="Deploying the .jar file." />     <property name="src" location="source" />    <property name="output" location="bin" />     <target name="main" depends="init, compile, compress, deploy">        <echo>            ${message}        </echo>    </target>       <target name="init">        <mkdir dir="${output}" />    </target>      <target name="compile">         <javac srcdir="${src}" destdir="${output}" />    </target>      <target name="compress">        <jar destfile="${output}/Project.jar" basedir="${output}">             <include name="*.class"/>            <include name="*.txt"/>        </jar>    </target>     <target name="deploy">        <scp trust="true"             file="${output}/Project.jar"               todir="user:password@000.000.000.000:cgi-bin"/>    </target> </project>

 

 

这是刚才的构造文件在Windows机器上运行时候的样子:

 

%ant

Buildfile: build.xml

 

init:

[mkdir] Created dir: C:\ant\ch08\scp\bin

 

compile:

[javac] Compiling 1 source file to C:\ant\ch08\scp\bin

 

compress:

[jar] Building jar: C:\ant\ch08\scp\bin\Project.jar

 

deploy:

[scp] Connecting to 000.000.000.000

[scp] Sending: Project.jar : 664

[scp] File transfer time: 1.32 Average Rate: 9502.27 B/s

[scp] done.

 

main:

[echo]

[echo] Deploying the .jar file.

[echo]

 

BUILD SUCCESSFUL

Total time: 12 seconds

 

小技巧: 正如在第4章的时候说过的一样,在一个构造文件中对密码和/或用户名的显式编码 (hardcoding-也有人称硬编码) 是一种不好的选择。使用属性会是一种较好的办法,象下面这样:

 

 

<scp todir="${username}:${password}@antmegacorp.com:   /home/steven/source" ...>

 

 

象下面这样把用户名和密码传递给Ant:

 

ant -Dusername=steven -Dpassword=opensesame

 

在文件被scp 方式所拷贝的时候,它的Unix文件许可并没有被保留(实际上它们得到的是UMASK许可)。如果你想保留Unix许可,用Unix下的scp 命令来代替(例如, <execexecutable="scp" ... >).

 

表 8-3. scp任务属性

 

 

 

 

你可以使用fileset 元素来选择一组文件来拷贝;如果你使用了fileset,你就必须为todir属性指定一个值. (fileset 元素只在你拷贝本地文件到远程主机时可用)

 

部署到Tomcat

 

作为servlet和JSP的参考Web服务器,Tomcat (可从[url]http://jakarta.apache.org/tomcat/[/url]得到),自从它包含了自定义的Ant部署方式,就变得更吸引Ant开发者。

从你的Tomcat5复制文件server/lib/catalina-ant.jar到Ant的lib目录来使用那些任务。

 

Tomcat部署任务包括部署, 重新加载,反部署 (卸载); 要使用他们,增加这些taskdef元素(在第11章讨论了) 到你的建造文件:

 

 

<taskdef name="deploy" classname="org.apache.catalina.ant.DeployTask"/> <taskdef name="reload" classname="org.apache.catalina.ant.ReloadTask"/><taskdef name="undeploy" classname="org.apache.catalina.ant.UndeployTask"/>

 

 

想使用这些任务, 你需要Tomcat管理员权限; 象下面这样编辑conf/tomcat-users.xml为一个用户名增加管理员权限(这里是admin)和口令:

 

 

<?xml version='1.0' encoding='utf-8'?><tomcat-users>  <role rolename="manager"/>  <role rolename="role1"/>  <role rolename="tomcat"/>   <user username="admin" password="password" roles="manager"/>  <user username="role1" password="tomcat" roles="role1"/>   <user username="tomcat" password="tomcat" roles="tomcat"/>  <user username="both" password="tomcat" roles="tomcat,role1"/> </tomcat-users>

 

 

你能像下面这样使用部署任务在Ant中部署一个Web应用程序到Tomcat:

 

 

<target name="install">     <deploy url="${manager.url}"         username="${manager.username}"        password="${manager.password}"         path="${app.path}"        localWar="file://${build}"/> </target>

 

 

在这里manager.url是Tomcat管理器的servlet的URL。

这servlet的缺省值名字是manager,因此看起来象[url]http://localhost:8080/manager[/url]。

app.path属性表示的是这个应用程序应该被部署的上下文路径(通常是/加上你想要在URL中联机访问的应用程序的的名字)。

build属性表示的是在你要在什么位置来建立Web应用程序,比喻说是Tomcat的webapps目录。

如果你已经安装一个应用程序并且想要Tomcat认出你最新的Java类,使用reload(重新加载任务)代替:

 

 

<target name="reload">     <reload url="${manager.url}"          username="${manager.username}"         password="${manager.password}"         path="${app.path}"/>  </target>

 

 

删掉一个Web应用程序, 使用undeploy任务:

 

 

<target name="remove">     <undeploy url="${manager.url}"        username="${manager.username}"         password="${manager.password}"        path="${app.path}"/> </target>

 

 

部署到Tomcat

 

更平常的情况是,你将不会在你想部署到的服务器上进行你的应用程序的开发。 你可以通过浏览器中的URL访问到Tomcat管理器的Servlet进而达到在一台运行了Tomcat的远程主机上部署的目的。

在Ant中实现这一点你需要get任务,当你把一个URL传递给它时它得到一份文件。如果你正在使用Java 1.4或更新版本,这个任务支持任何URL schema, 包括http:, ftp:, jar:,和 https:。如果你想要下载联机的内容,那么这个任务是较大的,或,如在本例中,通过URLs向联机的代码发布命令。

 

在开始部署前,这个例子使用get命令修改Ant主页并保存成ant.html:

 

 

<get src="http://ant.apache.org/" dest="ant.html"/>

 

 

你能通过传递一个要上传的Web应用程序的本地位置给管理器的servlet来实现为Tomcat上传Web应用程序的目的。

例如,从Windows的C:/ant/ch08/app上传一个Web应用程序,你将使用这个位置:

 

file:////C:\ant\ch08\app/

 

上传一个.war文件, 你在位置的最后加一个!来说明你上传的是一个文件而不是目录的内容,在Unix中象下面这样:

 

jar:file://///ant/ch08/app.war!/

例子8-3展示的是在实践的如何工作。

 

在这个例子中, 构造文件从C: \ant\deploy\app(org.antbook.ch08.Deploy)部署一个Web应用程序到Tomcat,它包含一个显示"Project Deployment"的servlet。

这是你要传递给的get任务的URL来告诉Tomcat管理器servlet你想要干什么:

 

[url]http://localhost:8080/manager/deploy?path=/deployment&amp;[/url]

war=file:////c:\ant\deploy\app/

 

在例子8-4你能看到如何工作。

例子8-4 部署与get(ch08/get/build.xml)

 

 

<?xml version="1.0" encoding="UTF-8" ?> <project default="main" basedir=".">    <property name="tomcat.port" value="8080" />         <property name="tomcat.username" value="admin" />         <property name="tomcat.password" value="password" />         <target name="main" >     <get src="http://localhost:8080/manager/deploy?path=/deployment&amp;      war=file:////c:\ant\deploy\app/"      dest="deploy.txt"      username="${tomcat.username}"      password="${tomcat.password}" />   </target>    </project>

 

 

下面是构造文件在实际中运行时候的样子:

 

%ant

Buildfile: build.xml

 

main:

[get] Getting: [url]http://localhost:8080/manager/deploy?[/url]

 

path=/deployment&war=file:////c:\ant\ch08\get\app/

 

BUILD SUCCESSFUL

Total time: 1 second

 

这是Tomcat输出到deploy.txt中的文件内容:

 

OK - Deployed application at context path /deployment

 

在部署以后, 通过[url]http://localhost:8080/deployment/org.antbook.ch08.Deploy[/url]显示出部署的servlet,如图8-1。

 

图 8-1. 部署到Tomcat

 

小技巧: 想要得到Tomcat管理servlet上的更多的信息,查看Tomcat的manager/html-manager-howto.html。

 

get任务的属性在表8-4列出.

表 8-4. get任务属性

 

 

小技巧: &nbsp;当verbose 被设置为true的时候,任务会每接受100K显示一个点(.)。

 

编译JSPs

 

当部署到服务器时, jspc任务是很有用的。 这个任务运行JavaServer Pages编译器并且把JSP页变成Java源代码,也可以在javac任务中实现。编译JSP页支持JSP网页的快速调用, 在没有完全的JDK服务器上的部署, 或让你不用部署就可以检查他们网页的语法。 缺省情况下,这个任务使用由Tomcat自带的Jasper JSP编译器。 拷贝Tomcat的jasper-compiler.jar和jasper-runtime.jar文件进Ant的lib目录来使用这个任务。 你将需要在Ant lib目录下放置由Tomcat带来的servlet.jar。

 

例如, 你有这JSP页面, greeting.jsp:

 

<HTML>  <HEAD>    <TITLE>Creating a Greeting</TITLE>  </HEAD>   <BODY>    <H1>Creating a Greeting</H1>    <%        out.println("Hello from JSP!");    //Display the greeting     %>  </BODY> </HTML>

 

 

例子8-5显示出怎么编译这JSP成greeting.java。

例子8-5 编译JSP页(ch08/jspc/build.xml)

 

 

<?xml version="1.0" ?> <project default="main">     <property name="message" value="Compiling the JSP...." />    <property name="src" location="source" />     <property name="output" location="bin" />     <target name="main" depends="init, compile">         <echo>            ${message}        </echo>    </target>      <target name="init">        <mkdir dir="${output}" />     </target>      <target name="compile">        <jspc srcdir="${src}"            destdir="${output}"            package="org.antbook.jsp"             verbose="9">            <include name="**/*.jsp" />        </jspc>    </target>  </project>

 

 

下面是你在运行构造文件时候所要看到的:

 

%ant

Buildfile: build.xml

 

init:

 

compile:

[jspc] Compiling 1 source file to

/home/steven/ant/ch08/jspc/bin/org/antbook/jsp

[jasperc] 2004-06-30 02:20:09 - Class name is:

greeting

[jasperc] 2004-06-30 02:20:09 - Java filename is:

/home/steven/ant/ch08/jspc/bin/org/antbook/jsp/greeting.java

[jasperc] 2004-06-30 02:20:09 - Accepted

org.apache.jasper.compiler.Parser$Scriptlet at /greeting.jsp(7,4)

[jasperc] 2004-06-30 02:20:09 - Compiling with: -encoding UTF8

 

main:

[echo]

[echo] Compiling the JSP....

[echo]

 

BUILD SUCCESSFUL

Total time: 3 seconds

 

下面是Java代码结果greeting.java看起来的样子:

 

 

package org.antbook.jsp.; import javax.servlet.*;import javax.servlet.http.*;import javax.servlet.jsp.*;import org.apache.jasper.runtime.*;  public class greeting extends HttpJspBase {     static {    }    public greeting( ) {    }     private static boolean _jspx_inited = false;     public final void _jspx_init( )          throws org.apache.jasper.runtime.JspException {    }     public void _jspService(HttpServletRequest request, HttpServletResponse          response)        throws java.io.IOException, ServletException {         JspFactory _jspxFactory = null;        PageContext pageContext = null;        HttpSession session = null;        .        .        .        out.println("Hello from JSP!");    //Display the greeting        ..        .    }}

 

 

下面是另一个例子,它编译JSP页,检查相关性, 并且使用javac任务为这JSP创建实际的bytecode:

 

 

<jspc    destdir="temp"    srcdir="${src}"    package="org.antbook.ch08">     <include name="**/*.jsp" /></jspc> <depend    srcdir="temp"    destdir="${bin}"    classpath="lib/app.jar"/> <javac    srcdir="temp"    destdir="${bin}"    classpath="lib/app.jar" />

 

 

在表8-5你能看见jspc任务的属性。

表 8-5. jspc任务的属性

 

 

jspc任务是一个基于目录的任务,因此被编的JSP文件用javac任务定位一样的方法定位文件, 它意味着你能使用嵌套元素,例如includes 和 excludes。你能使用嵌套的classpath和classpathref元素, 象嵌套的webapp元素一样。唯一出现在jspc任务中的webapp元素,指示JSP编译器创建一个全部Web应用程序程序。一个webapp元素的属性是basedir属性, 它设置应用程序的根目录。在它下级子目录必须有一个WEB-INF子目录。如果你使用这元素,这个任务使用编译器检查所有的相关性。

下面是一个使用webapp的例子:

 

 

<jspc    package="org.antbook.ch08">    <include name="**/*.jsp" />     <webapp basedir="${ch08}" /></jspc>

 

 

部署至EJB 容器

 

基本上,部署JavaBean到企业(EJB) 应用服务器相似于你已经看见的另外的Ant部署工程。你能使用这任务来打包并且部署EJB应用。例如,在例子8-6你会看到一个为JBoss服务器开发的构造文件; 构造文件首先创造一个.war文件然后把它打包进一个用来部署的.ear文件。

 

例8-6 一个Jboss EJB构造文件(ch08/ejb/build.xml)

 

 

<?xml version="1.0" ?><project default="main" basedir=".">     <target name="main" depends="init, compile, war, ear"/>     <target name="init">        <property name="src" value="${basedir}/src"/>         <property name="bin" value="${basedir}/output"/>        <property name="web" value="${basedir}/web"/>        <property name="descriptors"                            value="${basedir}/output/deploymentdescriptors"/>         <property name="eardir" value="${basedir}/output/ear"/>        <property name="wardir" value="${basedir}/output/war"/>        <property name="warfile" value="app.war"/>         <property name="earfile" value="app.ear"/>            <mkdir dir="${wardir}/WEB-INF"/>        <mkdir dir="${wardir}/WEB-INF/classes"/>         <mkdir dir="${eardir}/META-INF"/>    </target>        <target name="compile">        <javac destdir="${bin}" srcdir="${src}" includes="**/*.java" />     </target>        <target name="war">        <copy todir="${wardir}">            <fileset dir="${web}" includes="**/*.*" />         </copy>             <copy file="${descriptors}/web.xml" todir="${wardir}/WEB-INF" />            <copy todir="${wardir}/WEB-INF/classes">            <fileset dir="${bin}" includes="**/*.class" />         </copy>         <jar jarfile="${eardir}/${warfile}" basedir="${wardir}" />    </target>     <target name="ear">         <copy file="${descriptors}/application.xml"                todir="${eardir}/META-INF" />            <jar jarfile="${basedir}/${earfile}" basedir="${eardir}" />     </target>    </project>

 

 

这就是全部。尽管这构造文件使用标准的Ant任务工作,被构造了进Ant的任务使以ear任务开始的EJB应用程序工作更容易。

 

创建ear文件

 

创造ear任务是容易的.ear文件并且为在大多数ear需要的application.xml文件做特殊的预备。

它没有强制使用这个任务创造一个.ear文件,但是它能使生活更容易。

 

在表8-6你能看见这个任务的属性。

 

小技巧: ear任务是一个有为application.xml的特殊的待遇的对Jar任务的扩展。

你可以进行一样的操作,在一个zip或者jar任务中使用prefix(前缀)和fullpath属性。

 

表8-6 ear任务的属性

 

 

 

从zip任务的扩充的支持属性 prefix, fullpath,和src的zipfileset元素,在ear任务也同样可以办到。 嵌套的metainf元素规定一个fileset; fileset包括的所有的文件在.ear文件的META-INF目录的结束。

 

这个任务允许你使用appxml属性设定从什么地方得到application.xml。 下面是一个创建.ear文件的例子:

 

<ear destfile="${output}/app.ear" appxml="${src}/application.xml">     <fileset dir="${wardir}" includes="*.war"/></ear>

 

 

支持热部署

 

serverdeploy任务被设计成支持热部署 (在部署前你不必关闭服务器) 到EJB- aware的服务器。你设置action属性为你做见过的属性,像为Tomcat 管理器servlet设置使用了的那些: "deploy", "delete", 和 "undeploy"。

 

小技巧: 你可能需要vendor-specific来完成这个工作。

 

Ant提供build-end, 但是你的服务器需要提供Ant能连结与并且交往的一套部署工具。

在写这篇文章时, 这个任务仅仅支持Weblogic服务器和JOnAS 2.4开放源代码EJB服务器,但是对另外的EJB容器的支持应该快被增加。

这个任务有仅仅2属性,在表8-7被列出, 并且要求一些嵌套元素。

&nbsp;

表8-7 serverdeploy任务的属性

 

 

generic元素

 

如果你从服务器生产商得到Java类的部署代码,这是一个用于基于Java的部署的通用元素。如果有一个厂家特定的元素给serverdeploy使用,那当然使用它;但如果没有,那请使用通generic元素。

在表8-8此元素的属性被列出。

 

表8-8 generic元素的属性

 

 

generic元素支持嵌套的arg和jvmarg元素。下面是一个假定目标Web服务器是org.steven.j2ee.config.Deploy时,使用generic元素的部署文件的例子:

 

 

<serverdeploy action="deploy" source="${eardir}/app.ear">    <generic classname="org.steven.j2ee.config.Deploy"        classpath="${classpath}"        username="${user.name}"         password="${user.password}">        <arg value="-install"/>        <jvmarg value="-mx512m"/>    </generic> </serverdeploy>

 

 

weblogic元素

 

weblogic元素用于运行weblogic.deploy部署工具; 此工具的合法的actions包括:deploy, undeploy, list, update, 和 delete.。

在表8-9这些元素的属性被列出。

 

表8-9 weblogic元素的属性

 

 

下面是一个使用这个serverdeploy元素内部的元素来部署WebLogic服务器的例子:

 

 

<serverdeploy action="deploy"     source="${eardir}/app.ear">     <weblogic application="app"        server="ff19://server:7001"        classpath="${weblogic.home}/lib/weblogic.jar"        username="${user.name}"        password="${user.password}"         component="appserver,productionserver" /></serverdeploy>

 

 

jonas元素

 

jonas单元支持部署到JOnAS (Java Open Application Server, Java开放应用服务器) 服务器。 JOnAS部署工具 (org.objectweb.jonas.adm.JonasAdmin) 的有效actions有

deploy, undeploy, list 和 update.

 

在表8-10这元素的这些属性别列出。

 

表8-10。 jonas元素的属性

 

 

 

小技巧: 如果你准备根据从服务器回应的延期时间来编译一个延期任务,使用Ant waitfor任务。 你可以使用sleep任务来实现这个目的。

&nbsp;

jonas单元支持嵌套的classpath, arg,和jvmarg单元。 下面是一个使用serverdeploy部署到一个JOnAS服务器的例子:

 

 

<serverdeploy action="deploy" source="${eardir}/app.jar">    <jonas server="JOnAS5" jonasroot="${jonas.root}">        <classpath>             <pathelement path="${jonas.root}/lib/RMI_jonas.jar"/>        </classpath>    </jonas></serverdeploy>

 

 

 

Steve Holzner是O'Reilly出版的 upcoming Eclipse: A Java Developer's Guide的作者。