<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    jinfeng_wang

    G-G-S,D-D-U!

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      400 Posts :: 0 Stories :: 296 Comments :: 0 Trackbacks

    Written by Srikanth Shenoy November 2003

    Translated by jinfeng wang 2005年三月

    原文地址:http://www.theserverside.com/articles/article.tss?l=MavenMagic

    本文的翻譯已經原作者同意,轉載請保持原文。如有問題和意見可以和原作者或我聯系。

    Part 1: http://m.tkk7.com/jinfeng_wang/archive/2005/03/11/1956.html

    Part 3: http://m.tkk7.com/jinfeng_wang/archive/2005/03/15/2089.html

     

     

    Using Maven in J2EE Projects (J2EE項目中使用Maven)

    譯注:由于原文的source code是基于maven 1.0編寫的,部分代碼存在著一定的問題。此外,本文的部分內容所提到的問題在最新的maven 1.02中已經不存在了。

    In the previous section you saw how to use Maven to set up a project template, compile source files, create a jar and publish the artifact into the repository. There is much more to Maven than that. We will cover inheritance in Maven POM, setting up a Sample J2EE project, creating WARs, EJB-JARs, dependency jars and ultimately creating EARs. However let's first look at another important concept in Maven.

    從前文中,你已經學會了如何使用Maven使用項目模板、編譯源文件、創建jar包、將制品發布到倉庫中,Maven的基本功能都在這里了。下面我們將會介紹Maven POM的基礎、設置J2EE 演示項目、創建WAR、EJB-JAR、依賴包、以及最終的EAR。但在這之前,我們先看一下Maven中的另一個重要概念。

    In Maven, a project can produce only one artifact. The top-level project can have multiple sub projects and they in turn can have siblings too. But at the end, each of them can only produce one artifact. This makes a lot of sense if you consider how the Ant scripts are used to create multiple artifacts from a project - which gets confusing over time - to say the least. Typically, projects have a monolithic (or maybe a couple) source tree(s), from which all the dependency jars, WARs and EARs are created using different build scripts. At the end, the message of application partitioning is lost and classes are created in different packages without consideration to the classloader mechanism, making it even harder to keep build scripts up to date. Maven discourages this practice at the outset. Of course Maven gives you flexibility to override this practice. There are ways to produce multiple artifacts but that goes against the very spirit of Maven and has to be avoided unless absolutely essential.

    Maven中,一個項目只能生成一個制品。最頂層的項目可以含有多個子項目、也就是說,每個項目可以有兄弟項目。但無論如何,每個項目只能有一個制品。將Maven和Ant比較,“Ant可以為一個項目創建多個制品”,這確實是個需要花一段時間才能想通的問題。在典型情況下,每個項目都擁有一個(或多個)源代碼樹,從中可以build出各種jar、WAR、EAR。最后,項目中的所有分割信息都被隱藏了起來,根本沒有考慮classloader機制,直接編譯各包的class,很難保持構建腳本及時更新。Maven則不鼓勵這樣的工作方式,當然Maven靈活的提供了其他的方式實現此功能。在Maven中,你可以在一個項目中創建多個制品,但這本身就違反了Maven的精神,除非必要,我們都應該盡量去避免它。

     

    Customizing Maven with maven.xml 使用maven.xmlMaven進行定制

    Until now you saw how to compile java classes in a maven project and create jar files out of it. What if you wanted to customize Maven behavior? You can create a file called maven.xml in the same folder where project.xml resides. In this file, you can customize goals, define and pre and post goals.

    到現在為止,你已經知道在Maven項目中如何編譯java文件并將其打包,那么如何定制Maven的行為呢?你可以在Maven的項目中,創建一個maven.xml文件,其位置和project.xml相同。在此文件中,你可以定制goal,定義pre、post goal。

    Listing 6 shows a sample maven.xml. We are achieving quite a bit in this file. Look at the default goal for the project. The default goal is set to foobar-dist. A goal is equivalent of an Ant target. The default goal is the same as the default target in Ant. What this means is that the default goal is executed when you go to the directory containing this file and simply type maven. The foobar-dist goal is simply a wrapper on top of another goal called war:install. The "install" goal in the war plugin creates a war and publishes it into the repository. The "attainGoal" instructs maven to achieve the goal described by the name attribute.

    6 中給出了maven.xml的例子,從中我們可以學到很多東西。請看其中定義的該項目的默認goal,它被設為了foobar-dist。Maven中的goal和Ant中的target是相同的概念,Maven中的默認goal和Ant中的默認target相同。Maven的默認goal意味著:在該項目的目錄下,直接敲入“maven”命令,這時將會執行默認goal。這里例子中的foobar-dist是對“war:install”的封裝。在插件war中的“install”goal的作用是創建一個war,并將其發布到倉庫中。“attainGoal”則是告訴Maven去執行“name”屬性所描述的任務。

    The preGoal element instructs Maven to execute the defined tasks in the preGoal before achieving the goal specified in its name attribute. This can get confusing at times. Note that the preGoal name (java:compile) is different from the default goal (foobar-dist). The default goal for this project installs a war file. However the war plugin has to compile the java files in the project before creating the actual WAR archive. The preGoal specified is linked to this java:compile goal rather than the foobar-dist goal. In this case, the pre goal executes a Xdoclet maven plug in. We will use Xdoclet Maven plugin later in this article to generate tlds (tag library definitions) from the actual tag classes.

    PreGoal元素則告訴Maven在執行goal之前,執行在其“name”屬性中所描述的任務。有時候這也許會讓你犯糊涂,注意這里的preGoal 的name(java:compile)與默認goal(foobar-dist)的name是不同的。本項目中的默認goal是安裝一個war文件,但是在正式創建WAR文件之前,必須首先要編譯java文件,(譯者注:但是在編譯java之前,通過pregoal的定義,在java:compile調用之前,添加了新的調用xdoclet:webdoclet)。這里preGoal鏈接指向java:compile,而不是foobar-dist, 在本例中,pre goal將會執行Xdoclet插件的xdoclet:webdoclet。在這篇文章的后面,我們還會使用Xdoclet插件,從tag class中生成tld(tag library definitions)文件。(譯者注:表6中的preGoal調用了xdoclet:webdoclet,而此xdoclet插件可能是Maven沒有預先安裝的,需要執行“maven plugin:download -DartifactId=maven-xdoclet-plugin -DgroupId=xdoclet -Dversion=1.2”進行下載。此外,由于xdoclet目前的并不是在一個jar文件中的,所以還需要在project.xml中加載一些其他jar文件。)

    A postGoal can be specified for any of the implicit goals achieved as part of the default goal or for the default goal itself. In Listing 6, a postGoal is specified for the war:war goal, which gets executed just before war:install goal. The postGoal specifies that a certain directory have to be created after the WAR is built. Notice the use of standard ant tasks within the postGoal. In fact any of the ant tasks can be embedded within the goal, preGoal or postGoal. This is what makes Maven flexible. It is also very easy to abuse this flexibility by compiling and creating multiple artifacts using Ant tasks within Maven. In other words, you would have written Ant scripts under the hoods of Maven. That practice is discouraged and should be used if there is no other option. If you find yourself repeating the steps of putting ant tasks into Maven goals, what you need is a custom plugin.

    同樣的是,postGoal 可以做為任何goal的一部分,在表6中,postGoal則是專門為“war:war”定義的,這將在war:install之前被執行。(譯者注:因為表6中,為war:war定義了添加了postGoal擴展,而war:war將由war:install調用,因此文中說“這將在war:install之前被執行”。讀者不妨可以將postGoal這一段注釋掉執行以觀察執行結果,以進行比較。)在本例中,postGoal的定義是:在創建了WAR之后,創建一個目錄。注意,postGoal中使用了Ant中的task,事實上,Maven中可以嵌入任何Ant的task,無論是在goal, pregoal, postgoal中。它給Maven帶來了極大的靈活性,但是也很容易帶來Maven的誤用-“使用Ant的task進行代碼編譯、創建制品”,也就是說,你只是在Maven的帽子下面仍然依從Ant的方法編寫Ant腳本,如果有可能,請別使用這種方式完成任務。如果你發現你不斷的往Maven種添加Ant的task,那么你就該停下來去找一個適合的Maven插件。

    Listing 6 Sample maven.xml

    <project default="foobar-dist" xmlns:m="jelly:maven">
    <preGoal name="java:compile">
           <attainGoal name="xdoclet:webdoclet"/>
        </preGoal>
        <goal name="foobar-dist">
            <attainGoal name="war:install" />
        </goal> 
        <postGoal name="war:war">
          <mkdir dir="${test.result.dir}"/>
          <echo>Creating directories</echo>
       </postGoal>
     </project>

    A custom plugin is written in a file called plugin.jelly using the Jelly scripting language and bundled along with project.xml and other files into a jar and copied into the C:/Documents And Settings/<login-id>/.maven/plugins directory. This plugin is then available to all of your processes using Maven. We will customize the war plugin later in this article since it lacks some of the features we need.

    Maven的插件存放于C:/Documents And Settings/<login-id>/.maven/plugins目錄中,每個插件是一個jar文件,其中包括:使用Jelly腳本語言編寫的plugin.jell文件、project.xml 以及其他文件。因為war插件不能滿足一些我們的要求,后面我們將對war插件進行定制(譯者注:由于本篇文章寫于2003,它所使用的是Maven 1.0,其問題已經解決)。


    Figure 3 Inter-Project relationships for Foobar Travels

    3 Foobar Travels中的內部項目關系圖

    Let us now jump to applying Maven to J2EE projects. The most common J2EE artifact generated and deployed is the EAR. The EAR itself consists of dependency jars, ejb jars, wars and third party libraries. In other words, EAR is an aggregate artifact. For Foobar Travels, we will use the same project template as shown in Figure 2. Figure 3 shows the inter-project relationship and hierarchy. The master project template is defined at the top project level. A simplified master template is shown in Listing 7 only with the essential elements. A real one will have most of the items described in the section Maven basics. The key thing to note is that the dependencies are not declared in this template. This is because the master project.xml is just that - a template for other sub projects to extend. The only thing we have not touched upon from Listing 7 is the ${pom.artifactId}. I will explain this shortly in the context of extending the template. Figure 4 shows the structure of the EAR file generated by this project. You will find that the EAR content organization closely resembles the Maven project shown in Figure 3. In most of the J2EE project you would not deviate from a deployment artifact as in Figure 4. And when you stick to the usual route, Maven "out-of-the-box" build scripts work as is.

    現在讓我開始將Maven使用到J2EE項目中。J2EE項目中最經常生成發布的制品是EAR。EAR制品中包含的內容有:各種依賴包、EJB JAR、WAR以及第三方庫文件,EAR是一個聚合包。對于Foobar Travels,我們將使用圖2中的項目模板。圖3給出了其內部項目的依賴關系。項目的主模板將在項目的最頂層進行定義,表7中只給出了主模板中的關鍵元素信息。在Maven basics部分我們已經給出了實際中的絕大部分元素的信息。需要注意的是:在此模板中,并沒用給出依賴關系,這是因為主模板project.xml只是一個給子項目進行擴展的模板。在表7中我們唯一以前未曾接觸到的是${pom.artifactId},這將在講述如何擴展模板的時候對它進行解釋。圖4給出了本項目所生成的EAR文件的結構,你會發現這里EAR的內容和圖3中的Maven項目的內容緊緊的結合在一起。在絕大部分J2EE項目中,最后所部署的制品基本都和圖4所顯示項目的內容基本一致。如果你采用常規方法使用Maven的,它“out-of-the-box”構造腳本就可以如上使用了(譯者注:“out-of-the-box”是以前的一個開源項目,參考http://www.javaworld.com/javaworld/jw-04-2003/jw-0404-outofbox.html  )。

     



    Figure 4 The EAR structure for Foobar Travels

    4 FooBar TravelsEAR結構圖

     

    Listing 7 Master Project Definition Template
    表7主項目定義模板

    <project>
        
    <pomVersion>3</pomVersion>
        
    <id>foobar-online</id>
        
    <groupId>Foobar-Travels</groupId>
        
    <currentVersion>2.0</currentVersion>
        
    <name>Foobar Online Project</name>
        
    <organization>
            
    <name>Foobar Travels</name>
        
    </organization>
        
    <package>foobar.*</package>
        
    <distributionDirectory>
        /foobar/dist/${pom.artifactId}/
        
    </distributionDirectory>
        
    <dependencies/>
        
    <build>
          
    <sourceDirectory>${basedir}/src/java</sourceDirectory>
          
    <resources/>
        
    </build>
    </project>


    To summarize Figure 4, we have to build the following artifacts from the project shown in Figure 3.

    1. foobar-services-2.0.jar - The dependency jar
    2. reservationejb-2.0.jar - The Reservation EJB and create its Manifest file with Manifest Class-path pointing to the services jar file.
    3. personejb-2.0.jar - The Person EJB and create its Manifest file with Manifest Class-path pointing to the services jar file.
    4. foobar-web-2.0.jar - The Web application for Foobar Travels and create its Manifest file with Manifest Class-path pointing to the personejb, reservationejb and service jars
    5. application.xml - the J2EE application deployment descriptor.
    6. Build the EAR by including all of the above artifacts and also including the castor jar file since the services jar depends on it at runtime.

    總結圖4,我們將從圖3 的項目中創建出以下的制品:

    1、  foobar-services-2.0.jar -其所依賴的包

    2、  reservationejb-2.0.jar Reservation EJB,需要創建Manifest文件,其中聲明class-path,指向services jar文件。

    3、  personejb-2.0.jarPerson EJB,需要創建Manifest文件,其中聲明class-path,指向services jar文件。

    4、  foobar-web-2.0.jarFoobar Travels Web程序,需要創建Manifest文件,其中聲明class-path,指向personejbreservationejbservices jar文件。

    5、  application.xml J2EE應用的部署描述符。

    6、  創建EAR,其中包含上面的所有的制品、另外還需要包含castor.jar,因為service jar會在運行的時候使用它。

    Building the dependency jars (創建依賴包)

    Listing 8 shows the project definition for Services - a subproject in Maven. This subproject creates the foobar-services-2.0.jar file - a dependency library used by both ejbs and the web tier. Note that the definition extends from the master template in Listing 7. By extending from the parent, it inherits all the properties. It defines the dependency elements to indicate the dependencies on the J2EE APIs (not defined in the parent) and overrides the id, name and description defined in the parent.

    8中給出了子項目Services的定義,該項目將會創建foobar-services-2.0.jar,在EJB和Web程序中都會使用到該文件。注意,這里的定義侍從表7中的模板擴展而來的。通過擴展父模板,它繼承了所有的屬性。其中它定義了它將會依賴于J2EE API(這并沒有在父模板中定義),并且覆蓋(override)了父模板中的id, name and description。

    Listing 8 Services Sub-Project Definition
    表8 子項目Service的定義

    <project>
      
    <extend>${basedir}/../project.xml</extend>
      
    <id>foobar-services</id>
      
    <name>Foobar Services Framework</name>
      
    <package>foobar.service.*</package>
      
    <description>Services JAR project.</description>
      
    <dependencies>
            
    <dependency>
                
    <groupId>j2ee</groupId>
                
    <artifactId>j2ee</artifactId>
                
    <version>1.3.1</version>
            
    </dependency>
      
    </dependencies>
    </project>


    Now let us get back to the ${pom.artifactId} mentioned earlier (Listing 7). This lets you introduce polymorphism into Maven. At runtime, the value of ${pom.artifactId} for the Services sub-project is its id - foobar-services. Hence the value of the distribution directory for the Services project is /foobar/dist/foobar-services. In other words the pom can capture the variables and abstract them in a standard manner and establish a procedural approach instead of the chaotic one.

    現在讓我講解前面提到的${pom.artifactId}(表7中),它允許你將多態(polymorphism)引入到Maven中。在運行的時候, ${pom.artifactId}的具體值是子項目Services的id:foobar-services.因此Services項目的distributionDirectory值是:/foobar/dist/foobar-services.換句話說,POM能夠捕捉變量的值,并且在運行的時候通過一種標準方式,及時用確切值替換原變量。

    Now let us introduce you to the maven.xml for the Services Project. Technically speaking, maven.xml is not needed since you can always go to this sub project and execute maven jar:install. However as we will see later, having a maven.xml will help us eliminate manual execution of Maven from every sub-project. The maven.xml for the Services project looks as follows.

    下面介紹Services項目中的maven.xml。從技術角度來看,maven.xml并不是必需的,你可以到該子項目的目錄下執行命令“jar:install”。但是我們后面就可以看到,擁有這樣的一個maven.xml文件將會極大的幫助我們,不再需要人工到每個子目錄下面執行maven命令。Services子項目的maven.xml文件內容如下:

    <project>
      
    <extend>${basedir}/../project.xml</extend>
      
    <id>foobar-services</id>
      
    <name>Foobar Services Framework</name>
      
    <package>foobar.service.*</package>
      
    <description>Services JAR project.</description>
      
    <dependencies>
            
    <dependency>
                
    <groupId>j2ee</groupId>
                
    <artifactId>j2ee</artifactId>
                
    <version>1.3.1</version>
            
    </dependency>
      
    </dependencies>
    </project>



    Building the EJB jars (構建EJB Jar

    After having built the dependency jars let us turn our focus to building the ejb jars. This is no different, since there is already a ejb plugin and you can use the ejb:install goal to create and publish the ejb jars. However we would also like to remind you that the ejb jar (loaded by the EJB class loader) depends on the Services built in the previous step (See Figure 4). What this means for you is that the ejb manifest classpath should point to the foobar-services-2.0 jar. Listing 9 shows the project.xml for the Reservation EJB jar. Other ejb project definitions are similar.

    在創建了依賴包后,我們開始創建ejb jar。毫無區別的是,Maven中已經有了ejb插件 ,你可以使用ejb:install創建和發布ejb jar。但是我必須提醒你,ejb jar(由EJB class loader載入)依賴于前一步圖4中剛創建的Services包。也就是說,你必須在ejb manifest中聲明classpath,將它指向foobar-services-2.0 jar。表9給出了Reservation EJB jar的project.xml。其他EJB項目的定義與此類似。

    NOTE: In the downloadable example supplied with this article, no EJBs are included. The reason is to have even non-ejb developers using Tomcat to see Maven in action. However this section describes what it takes to build EJBs with Maven.

    注意:在供下載的例子中,并沒有包含EJB程序。因為保證非EJB開發者可以在Tomcat中使用,了解Maven的使用方法。但是本段所講的內容則是如何使用Maven構建EJB

    As usual the ejb project depends on the J2EE jars. However since it also depends on the foobar-services-2.0.jar (loaded by the EAR class loader), it has to add that jar file name to its manifest classpath. You can achieve this by setting the property ejb.manifest.classpath to be true. The Maven variable, pom.currentVersion stands for the current version of the project. In our case, it is 2.0. This setting indicates that the version of services project on which the ejb project depends is the same as the current version of the ejb project. This version is set on the parent project template. For future releases, the version number need not be changed for every dependency in every project. Just change it in the Master project template and it takes effect everywhere. Ah, the beauty of inheritance!

    和平常一樣,EJB項目會依賴J2EE包,但是他還依賴foobar-services-2.0.jar(由EAR Class loader載入)。因此不得不將此jar的文件名機阿然到manifest的classpath中。你可以將ejb.manifest.classpath的值設為true。pom.currentVersion代表項目的當前版本,在我們的例子中是2.0。這里的設置意味著EJB項目和其所依賴的Services項目兩者的版本號是一樣的。這里的版本號被設置為父項目模板中的版本。在將來發布的時候,則無需一一修改各個子項目的版本號,直接修改父項目的模板即可。這就是繼承的作用。

    Listing 9 Reservation EJB Project Definition 表9 Reservation EJB項目的定義

    <project>
      <extend>${basedir}/../project.xml</extend>
      <id>reservationejb</id>
      <name>Foobar Reservation Components</name>
      <package>foobar.reservation.*</package>
      <description>Reservation Components project</description>
      <dependencies>
        <dependency>
          <groupId>j2ee</groupId>
          <artifactId>j2ee</artifactId>
          <version>1.3</version>
        </dependency>
        <dependency>
          <groupId>Foobar-Travels</groupId>
          <artifactId>foobar-services</artifactId>
          <version>${pom.currentVersion}</version>
          <properties>
            <ejb.manifest.classpath>true</ejb.manifest.classpath>
          </properties>
        </dependency> 
      </dependencies>
    </project>

    The discussion of building the ejb jars is incomplete without mentioning the maven.xml file. This file is not straight forward as in the services project. Listing 10 shows the maven.xml for the Reservation EJB project. There are a few things happening here. First, the foobar-dist goal is used as a wrapper for attaining the goal ejb:install. One of the first goals to be achieved during the install is init, when the file system and other resources are initialized and then the ejb classes are compiled. The compiler expects to find the home, local and remote interfaces, failing which it will throw a compiler error. This is where XDoclet comes into play.

    在討論構建ejb jar的時候,必須要談到其maven.xml。這里的maven.xml則不像Services項目中那樣加納隊那了。表10給出了其定義,有以下幾點內容:首先,foobar-dist goal封裝了ejb:install;在“install”剛初始化的之前,文件系統和其他資源必須首先被初始化,隨后編譯ejb的class文件。編譯器將嘗試尋找home、local、interface,如果失敗,則編譯報錯。這就是XDolet所搬演的角色。

    Listing 10 maven.xml for the Reservation EJB Project

    10 Reservation EJB項目的maven.xml

    <project default="foobar-dist" xmlns:m="jelly:maven"
                                    xmlns:ant
    ="jelly:ant">
       
    <goal name="foobar-dist">
         
    <attainGoal name="ejb:install" />
       
    </goal>

       
    <preGoal name="ejb:init">
          
    <attainGoal name="xdoclet:ejbdoclet"/>
       
    </preGoal>

       
    <postGoal name="ejb:install">
          
    <ant:property name="maven.ejb.install.dir"
           value
    ="${maven.repo.local}/${pom.artifactDirectory}/ejbs"/>
          
    <ant:mkdir dir="${maven.ejb.install.dir}"/>
          
    <ant:copy file="${maven.build.dir}/${maven.final.name}.jar"
                tofile
    ="${maven.ejb.install.dir}/../
                         jars/${maven.final.name}.jar"
    />
       
    </postGoal>
    </project>


    XDoclet is an open source project hosted on the SourceForge. By using EJB Doclet specific tags in the Bean class (the implementation class), you signal the XDoclet to generate the home, local and remote interfaces. You will also provide the jndi names, and other information using similar tags. On parsing the file, the XDoclet will also generate appropriate deployment descriptors. Now let us get back to see how it fits in here.

    XDoclet是sourceforge中的一個開源項目,通過在Bean class文件(EJB 實現文件)中的EJB Doclet 描述tag,告訴Xdoclet產生home, local interface和remote interface。你還可以使用類似tag,寫入jndi name以及其他信息。Xdoclet經過分析源文件之后,將會生成相應的部署描述符。現在讓我們回頭看它是怎么運行的。

    XDoclet provides Maven plugins for generating the above-mentioned artifacts. By specifying the ejbdoclet as the preGoal for ejb:init, you will generate home, local and remote interfaces and xml deployment descriptors just in time for the compilation.

    XDoclet為Maven提供了插件,可以生成上述的制品。通過將ejbdoclet設置為ejb:init的pregoal,它將會在編譯期間幫你生成home, local interface, remote interface和部署描述符xml文件。

    Now let us look at the postGoal for ejb:install. As you know, the ejb:install generates the ejb jar as the artifact and puts it in the repository in the location "C:/Documents And Settings/<login-id>/.maven/repository/Foobar-Online/jars". Suppose that you want the ejbs to be in a separate directory called ejbs instead of the jars, you have to do it after the ejb:install is finished with its business. That's why it is a postGoal. For those familiar with Ant, the postGoal is nothing but a collection of Ant tasks. Again, a couple of Maven specific properties are used. Don't try to remember all of the Maven defined properties at once. Over time, these will become second nature.

    現在讓我們看一下ejb:install的postGoal吧。正如你所知道的,ejb:install將會生成ejb jar制品,并將其發布到倉庫C:/Documents And Settings/<login-id>/.maven/repository/Foobar-Online/jars目錄。假設你想將ejb部署到名為“ejbs”的目錄中,而不是目錄“jars”,這必須在ejb:install完成之后才能做。這就是為何這里使用postGoal的原因。熟悉Ant的讀者就能知道,這里的postGoal是Ant的task的集合,這里使用了Maven的許多特有屬性。并沒有必要一次性的記住Maven所定義的所有屬性,過一段時間,這些就變成你的第二本能啦。

    You will notice there are two distinct categories of properties - those with their name beginning with pom and the rest of them. The properties with their names beginning with pom are the individual elements in the project.xml. For instance, the currentVersion element defined in project.xml has a property with the name pom.currentVersion and so on. The project.xml is loaded to create the POM model by Maven. POM model attribute values are evaluated by using the $ sign before the attribute names. As more plugins are added new properties emerge. This is going to be a challenge. You may not find adequate documentation of these properties. The only way to find out is by opening the scripts for each of these plugins in plugin.jelly file. Luckily there aren't very many properties that you will have to know.

    注意到這里有兩類屬性:名字以pom開頭算第一類,其余的是第二類。第一類的屬性是在project.xml中定義的元素。例如project.xml定義的currentVersion元素可以使用pom.currentversion進行訪問,其他也是如此。Maven將會載入project.xml形成POM模型。可以在屬性名前面加$開頭訪問其屬性值。隨著插件的增多,這確實會帶來一定的問題。你根本無法找到這些屬性的文檔,唯一能做的就是打開每個插件的pligin.jelly,查看其內容。幸好,你并不需要了解太多的屬性。

    In your project, if you find yourself writing the same pregoals and postgoals for every ejb subproject for example, it is time to roll your own plugin.

    在你的項目中,如果你為每個ejb都寫了相同的pregoal、postgoal,那么你就該寫自己的插件啦。

     

    Building the WAR (構建war)

    After the ejb jar, it is war time. We will accomplish quite a bit in this section. First we will introduce you to the project.xml. Then we will add a minor missing functionality into the war plugin. Then we will show you how to use XDoclet to generate tlds for a sample tag. Then we will end the section with maven.xml.

    在創建了Ejb jar后,該創建war包了。我們將在后面對此進行講述。首先我們介紹project.xml,然后將給war插件添加一些未曾有的功能(譯注:在maven 1.02版本中,問題已經解決),接著將演示如何使用XDoclet生成為tag例子生成tld文件,最后介紹maven.xml。

    Listing 11 shows the project.xml for the Foobar web application. The actual project definition has much more dependencies and is downloadable. Here we are showing only the relevant portions to illustrate the concepts. The important part is the dependencies section. The web application depends on the J2EE APIs provided by the container at runtime as well as compile time. However there is no need to bundle the J2EE API with the WAR since it is the servlet container's responsibility. In addition the web application depends on Struts 1.1 jar file. The property setting <war.bundle>true</war.bundle> indicates that struts.jar has to be bundled with the WAR. Whenever the war plugin is instructed to bundle the jars, it puts them under the WEB-INF/lib directory of the WAR. Compare this to manually copying the jars into the WEB-INF/lib directory in Ant. The WAR also depends on the Foobar Services jar file, foobar-services-2.0.jar. However we do not want to copy this jar into the WEB-INF/lib since it is a dependency library and shared by both the web tier and the ejbs. (Recall that any jars and classes residing in WEB-INF/lib and WEB-INF/classes are loaded by the WAR class loader.) Hence we set the war.bundle property as false for foobar-services jar file. You get all this functionality out of the box with Maven war plugin.

    11給出了Foobar Web程序的project.xml,實際的project.xml文件的內容要比這里演示的內容多許多。這里我們僅介紹相關部分,講解其概念。最關鍵的部分就是depencies部分,該Web程序依賴于J2EE API,它們將由容器在編譯器和運行時提供。因此無需在WAR中加入J2EE的包,這時Servlet容器的責任。另外,該程序依賴于Structs 1.1 jar文件,<war.bundle>true</war.bundle>表示這struts.jar將會打入到WAR包中。war插件將會把jar文件加入到WAR的WEB-INF/lib目錄下,而Ant中則需要將jar文件手工拷貝到WEB-INF/lib目錄。WAR還依賴于Foobar Services的foobar-services-2.0.jar文件,但是我們并不需要將它拷貝到WEB-INF/lib目錄,因為該包是依賴包,EJB、WEB都需要使用此包(記住所有在WEB-INF/libWEB-INF/classes 的jar或class都是由WAR class loader所加載的) 。因此將foobar-services jar文件的war.bundle 屬性設為false。所有的這一切都可以通過Maven的war插件完成。

    Listing 11 maven.xml for the Web Project

    <project>
      <extend>${basedir}/../project.xml</extend>
      <id>foobar-web</id>
      <name>Foobar web application</name>
      <package>foobar.webapp.*</package>
      <description>Foobar Web project.</description>
      <dependencies>
        <dependency>
          <groupId>j2ee</groupId>
          <artifactId>j2ee</artifactId>
          <version>1.3.1</version>
        </dependency>

        <dependency>
          <groupId>jakarta-struts</groupId>
          <artifactId>jakarta-struts</artifactId>
          <version>1.0.2</version>
          <properties>
            <war.bundle>true</war.bundle>
          </properties>
        </dependency>
        <dependency>
          <groupId>Foobar-Travels</groupId>
          <artifactId>foobar-services</artifactId>
          <version>${pom.currentVersion}</version>
          <properties>
             <war.bundle>false</war.bundle>
            <war.manifest.classpath>true</war.manifest.classpath>
          </properties>
        </dependency>
      </dependencies>
    </project>

     However the Maven war plugin lacks one feature. It does not have the capability to set the manifest classpath. Without this feature you cannot expect to use dependency libraries. Hence I decided to add this feature to the war plugin. Only two simple changes were required to achieve this. I decided to illustrate this change to show how intuitive and easy it is to write plugins in Jelly or customize the ones that already exist. Open the plugin.jelly for the war plugin from C:/Documents And Settings/<login-id>/.maven/plugins/maven-war-plugin-<version>-[SNAPSHOT]. These changes have to be done in the goal named war (The actual WAR - deployment archive, is built in a goal named as war in the war plugin). Add the following code in that goal.

    但是目前的Maven的war插件還存在著一定的缺陷,它無法設置manifest的classpath(譯者注:此功能已經在Maven 1.02中完成),你無法正常的使用依賴庫。因此我決定給插件添加以下功能,只需要做兩處改變即可。下面講述如何使用Jelly簡單的修改現有插件,或者自己寫一個插件。在C:/Documents And Settings/<login-id>/.maven/plugins/maven-war-plugin-<version>-[SNAPSHOT]目錄中打開war插件的plugin.helly,找到名為war的goal(事實上WAR發布包就是使用war插件中的名為war的構建的),添加下面的內容。

    <j:forEach var="dep" items="${pom.dependencies}">
      <j:if   test="${dep.getProperty('war.manifest.classpath')=='true'}">
        <j:set var="maven.war.classpath"
               value="${maven.war.classpath} ${dep.artifact}"/>
      </j:if>
    </j:forEach>

    This code iterates over each of the dependencies listed in the project.xml (identified by pom.dependencies) and checks if the war.manifest.classpath property is set to true. If so, then it appends that artifact name to a property called maven.war.classpath.

    這里的代碼將會遍歷project.xml中的所有依賴包(由pom.dependencies可以辨別),然后檢查war.manifest.classpath是否被設為true。如果真,則將此制品的名字加入到屬性maven.war.classpath

    The second change is needed when the manifest file is written out. The manifest file is created by the ant plugin by executing a goal named manifest. The manifest creation code is shown below. The line in bold is the line I inserted to set the manifest classpath attribute. This uses the previously set maven.war.classpath.

    第二處改變在manifest文件生成的時候。在執行名為manifest的goal的時候,Maven將調用Ant的插件,創建生成manifest文件。Manifest的創建代碼如下顯示。黑體部分是我寫的設置manifest的classpath屬性的代碼,它將使用到前面設置的maven.war.classpath屬性。

    <ant:manifest>
      <ant:attribute name="Built-By" value="${user.name}" />
      <ant:attribute name="Class-Path" value="${maven.war.classpath}"/>
      <ant:section name="${pom.package}">
        <ant:attribute name="Specification-Title"
                       value="${pom.artifactId}" />
        <ant:attribute name="Specification-Version"
                       value="${pom.currentVersion}" />
        <ant:attribute name="Specification-Vendor"
                       value="${pom.organization.name}" />
      </ant:section>
    </ant:manifest>

    That was simple wasn't it! Hopefully this will inspire you to write your own plugins when needed, instead of repetitively adding tasks into preGoals and postGoals.

    非常簡單,不是么?也許這會激發你在必要的時候寫自己的插件。而不是象先前那樣不斷的在任務中插入preGoalpostGoal

    Written by Srikanth Shenoy November 2003

    Translated by jinfeng wang 2005年三月

    原文地址:http://www.theserverside.com/articles/article.tss?l=MavenMagic

    本文的翻譯已經原作者同意,轉載請保持原文。如有問題和意見可以和原作者或我聯系。

    Part 1: http://m.tkk7.com/jinfeng_wang/archive/2005/03/11/1956.html

    Part 3: http://m.tkk7.com/jinfeng_wang/archive/2005/03/15/2089.html

    posted on 2005-03-14 16:44 jinfeng_wang 閱讀(2660) 評論(0)  編輯  收藏 所屬分類: mavenZZ
    主站蜘蛛池模板: 亚洲免费在线视频观看| 亚洲成AV人在线观看天堂无码| xvideos永久免费入口| 亚洲成电影在线观看青青| 国产免费拔擦拔擦8x| 2019中文字幕在线电影免费| 一级特黄特色的免费大片视频| 亚洲美女视频免费| 亚洲国产成人一区二区三区| 国产免费直播在线观看视频| 久久精品网站免费观看| 久久99热精品免费观看动漫 | 黄色毛片免费在线观看| 亚洲人成在线播放| 亚洲精品在线免费观看| 亚洲精品无码鲁网中文电影| 国产成人精品久久亚洲高清不卡 | 日本特黄a级高清免费大片| 免费精品国产日韩热久久| 99热在线免费播放| 在线永久免费的视频草莓| 精品无码AV无码免费专区| 一区二区三区在线免费看| 大地资源中文在线观看免费版| av午夜福利一片免费看久久| 一级成人毛片免费观看| 在线观看免费黄网站| 永久免费av无码网站yy| 在线毛片片免费观看| 24小时日本电影免费看| 免费理论片51人人看电影| 永久黄网站色视频免费观看| 亚洲成人高清在线| 亚洲国产精品一区| 国产亚洲中文日本不卡二区| 久久乐国产精品亚洲综合| 亚洲国产精品一区二区第一页| 亚洲成A∨人片在线观看无码| 国产AV旡码专区亚洲AV苍井空| 麻豆安全免费网址入口| 亚洲精品免费在线观看|