Maven Archetypes Part 3: 怎样构建一个多模块工程?

原文地址

源码下载传送门

欢迎回来

如果你没有阅读前面章节,或对Maven archetypes不熟悉,你会看不懂,XD。

到目前为止,我们已经创建了一个archetype,可以生成能打包为jar且会say Hello word的工程,并且包含了一个单元测试类。另一个场景是你想要创建一个多模块的工程。举个栗子,你想要一个工程,包含一个model和一个webapp模块,或者一个client一个server模块能传输一个共有的类型对象。

为达到这个目的,并不会花费你太多精力。很多的工作我们在之前的例子中已经完成了。

重温前情,然后添加一些新东西

让我们从上一节所创建的archetype工程结构开始:

$ tree
.
|____pom.xml
|____src
| |____main
| | |____resources
| | | |____archetype-resources
| | | | |____pom.xml
| | | | |____src
| | | | | |____main
| | | | | | |____java
| | | | | | | |______packageInPathFormat__
| | | | | | | | |____App.java
| | | | | |____test
| | | | | | |____java
| | | | | | | |______packageInPathFormat__
| | | | | | | | |____AppTest.java
| | | |____META-INF
| | | | |____maven
| | | | | |____archetype-metadata.xml

首先,我们需要将之前能够打包成jar的项目移动到下一层目录。我们的多模块项目的顶层目录装父项目,父项目提供一个pom。

$ mkdir src/main/resources/archetype-resources/__artifactId__-model
$ mv src/main/resources/archetype-resources/src src/main/resources/archetype-resources/__artifactId__-model/
$ mv src/main/resources/archetype-resources/pom.xml src/main/resources/archetype-resources/__artifactId__-model/

你应该注意到了__artifactId__-model。如果你记得第二节的内容,如果使用双下划线在参数的前面和后面,Maven将会将这个参数名替换成对应的参数内容。根据上面的目录结构,如果我们从archetype生成的项目的artifact id为sample-project,这个目录将创建为sample-project-model

创建和重构pom文件

现在我们将根目录的内容移动到子目录去了,在根目录里还没有东西。我们需要创建一个pom,作为多模块项目的parent。现在新建一个文件src/main/resources/archetype-resources/pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <groupId>${groupId}</groupId>
  <artifactId>${artifactId}</artifactId>
  <version>${version}</version>
  <packaging>pom</packaging>
  <name>${artifactId}</name>

  <modules>
    <module>${artifactId}-model</module>
  </modules>

</project>

这个pom和第一节中的pom非常类似,除了与模块关联的列表。注意我们这里用了${artifactId}-model来和刚刚创建的模块对应。

我们也需要更新模块里的pom,来和parent做对应:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>${groupId}</groupId>
    <artifactId>${artifactId}</artifactId>
    <version>${version}</version>
  </parent>
  <artifactId>${artifactId}-model</artifactId>
  <packaging>jar</packaging>
  <name>${artifactId}-model</name>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.3.2</version>
        <configuration>
          <encoding>UTF-8</encoding>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit-dep</artifactId>
      <version>4.10</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

</project>  

你可能注意到了,节点<version><groupId>已经被移除。父项目会让他的子模块继承这些值,所以在子模块中不必重复他们。

我们也可以进一步配置。首先,我们可以将build区块移动到父项目中,让所有子模块继承,这样所有子模块拥有同样的compile配置,我们也可以在依赖管理(dependency management)中定义将junit依赖让所有模块依赖版本一致。
在我们做了这些改变后,我们的父项目parent的pom(src/main/resources/archetype-resources/pom.xml)应该是下面这个样子:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <groupId>${groupId}</groupId>
  <artifactId>${artifactId}</artifactId>
  <version>${version}</version>
  <packaging>pom</packaging>
  <name>${artifactId}</name>

  <modules>
    <module>${artifactId}-model</module>
  </modules>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.3.2</version>
        <inherited>true</inherited>
        <configuration>
          <encoding>UTF-8</encoding>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit-dep</artifactId>
        <version>4.10</version>
        <scope>test</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

</project>

我们的子模块的pom(src/main/resources/archetype-resources/artifactId-model/pom.xml)应该长这个样:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>${groupId}</groupId>
    <artifactId>${artifactId}</artifactId>
    <version>${version}</version>
  </parent>

  <artifactId>${artifactId}-model</artifactId>
  <packaging>jar</packaging>
  <name>${artifactId}-model</name>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit-dep</artifactId>
    </dependency>
  </dependencies>

</project>

更新archetype的metadata

到现在为止,我们所有的更新都不会有什么结果,知道我们更新了archetype的metadata。现在就让我们来开启这神奇的一页:

<archetype-descriptor name="sample-archetype">
  <fileSets>
    <fileSet filtered="true">
      <directory></directory>
      <includes>
        <include>pom.xml</include>
      </includes>
    </fileSet>
    <fileSet filtered="true">
      <directory>__artifactId__-model</directory>
      <includes>
        <include>pom.xml</include>
      </includes>
    </fileSet>
    <fileSet filtered="true">
      <directory>__artifactId__-model/src/main/java</directory>
      <includes>
        <include>**/*.java</include>
      </includes>
    </fileSet>
    <fileSet filtered="true">
      <directory>__artifactId__-model/src/test/java</directory>
      <includes>
        <include>**/*.java</include>
      </includes>
    </fileSet>
  </fileSets>
</archetype-descriptor>

创建webapp模块

我们已经添加了第一个模块。接下来,我们我们将创建第二个模块:

新建文件夹:

mkdir -p src/main/resources/archetype-resources/__artifactId__-webapp/src/main/java/__packageInPathFormat__

如果我们创建webapp,我们需要servlet api。让我们在parent pom中添加一个scope为provided的依赖。我们也需要添加一个带有version的model模块,这样,我们可在webapp里引入他的时候不用指定版本:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit-dep</artifactId>
      <version>4.10</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>${groupId}</groupId>
      <artifactId>${artifactId}-model</artifactId>
      <version>${version}</version>
    </dependency>
  </dependencies>
</dependencyManagement>

我们也需要添加webapp模块到我们parent项目pom的modules列表中:

<modules>
  <module>${artifactId}-model</module>
  <module>${artifactId}-webapp</module>
</modules>

现在,让我们来创建webapp模块的pom(src/main/resources/archetype-resources/artifactId-webapp/pom.xml)。我们将添加servlet-api的依赖,和我们第一个模块model的依赖,还有Maven Jetty plugin,这样我们可以在创建项目后从Maven启动它:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>${groupId}</groupId>
    <artifactId>${artifactId}</artifactId>
    <version>${version}</version>
  </parent>

  <artifactId>${artifactId}-webapp</artifactId>
  <packaging>war</packaging>
  <name>${artifactId}-webapp</name>

  <build>
    <plugins>
      <plugin>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>maven-jetty-plugin</artifactId>
        <version>6.1.26</version>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
    </dependency>
    <dependency>
        <groupId>${groupId}</groupId>
        <artifactId>${artifactId}-model</artifactId>
      </dependency>
  </dependencies>

</project>

我们还需要在src/main/webapp/WEB-INF路径中添加web.xml。让我们先创建web.xml所在目录:

mkdir -p src/main/resources/archetype-resources/__artifactId__-webapp/src/main/webapp/WEB-INF
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

  <servlet>
    <display-name>${artifactId}</display-name>
    <servlet-name>${artifactId}</servlet-name>
    <servlet-class>${package}.Servlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>${artifactId}</servlet-name>
    <url-pattern>/${artifactId}</url-pattern>
  </servlet-mapping>

</web-app>

我们可以过滤并替换这个文件中的${artifactId}等参数。
我们也需要一个基础的servlet类去匹配在web.xml文件中的定义。在路径src/main/resources/archetype-resources/__artifactId__-webapp/src/main/java/__packageInPathFormat__/Servlet.java创建一个类,以下是Servlet.java中内容:

package ${package};

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Servlet extends HttpServlet {

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {

    response.setStatus(200);
    PrintWriter writer = response.getWriter();
    writer.write(App.message());
  }

}

更新archetype的metadata

我们需要再一次更新src/main/resources/META-INF/maven/archetype-metadata.xml,将webapp模块的内容加入。这里是最终的archetype-metadata.xml文件的样子:

<archetype-descriptor name="sample-archetype">
  <fileSets>
    <fileSet filtered="true">
      <directory></directory>
      <includes>
        <include>pom.xml</include>
      </includes>
    </fileSet>
    <fileSet filtered="true">
      <directory>__artifactId__-model</directory>
      <includes>
        <include>pom.xml</include>
      </includes>
    </fileSet>
    <fileSet filtered="true">
      <directory>__artifactId__-model/src/main/java</directory>
      <includes>
        <include>**/*.java</include>
      </includes>
    </fileSet>
    <fileSet filtered="true">
      <directory>__artifactId__-model/src/test/java</directory>
      <includes>
        <include>**/*.java</include>
      </includes>
    </fileSet>
    <fileSet filtered="true">
      <directory>__artifactId__-webapp</directory>
      <includes>
        <include>pom.xml</include>
      </includes>
    </fileSet>
    <fileSet filtered="true">
      <directory>__artifactId__-webapp/src/main/java</directory>
      <includes>
        <include>**/*.java</include>
      </includes>
    </fileSet>
    <fileSet filtered="true">
      <directory>__artifactId__-webapp/src/main/webapp/WEB-INF</directory>
      <includes>
        <include>web.xml</include>
      </includes>
    </fileSet>
  </fileSets>
</archetype-descriptor>

让我们来最后审视项目结构,奏是这个造型:

$ tree
.
|____pom.xml
|____src
| |____main
| | |____resources
| | | |____archetype-resources
| | | | |______artifactId__-model
| | | | | |____pom.xml
| | | | | |____src
| | | | | | |____main
| | | | | | | |____java
| | | | | | | | |______packageInPathFormat__
| | | | | | | | | |____App.java
| | | | | | |____test
| | | | | | | |____java
| | | | | | | | |______packageInPathFormat__
| | | | | | | | | |____AppTest.java
| | | | |______artifactId__-webapp
| | | | | |____pom.xml
| | | | | |____src
| | | | | | |____main
| | | | | | | |____java
| | | | | | | | |______packageInPathFormat__
| | | | | | | | | |____Servlet.java
| | | | | | | |____webapp
| | | | | | | | |____WEB-INF
| | | | | | | | | |____web.xml
| | | | |____pom.xml
| | | |____META-INF
| | | | |____maven
| | | | | |____archetype-metadata.xml

安装archetype,生成项目然后运行webapp

现在先install archetype,然后去要生成项目的目录,然后生成它:

$ mvn clean install
$ cd ..
$ mvn archetype:generate -DarchetypeCatalog=local
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] >>> maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom >>>
[INFO] 
[INFO] <<< maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom <<<
[INFO] 
[INFO] --- maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Interactive mode
[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)
Choose archetype:
1: local -> com.theotherian.archetype:sample-archetype (sample-archetype)
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 1: 1
Define value for property 'groupId': : com.theotherian
Define value for property 'artifactId': : sample-project
Define value for property 'version':  1.0-SNAPSHOT: : 
Define value for property 'package':  com.theotherian: : 
Confirm properties configuration:
groupId: com.theotherian
artifactId: sample-project
version: 1.0-SNAPSHOT
package: com.theotherian
 Y: : 
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: sample-archetype:1.0-SNAPSHOT
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.theotherian
[INFO] Parameter: artifactId, Value: sample-project
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: com.theotherian
[INFO] Parameter: packageInPathFormat, Value: com/theotherian
[INFO] Parameter: package, Value: com.theotherian
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: groupId, Value: com.theotherian
[INFO] Parameter: artifactId, Value: sample-project
[WARNING] Don't override file /Users/isimpson/sample-projects/sample-project/pom.xml
[INFO] project created from Archetype in dir: /Users/isimpson/sample-projects/sample-project
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 14.574s
[INFO] Finished at: Sat May 12 22:14:07 MDT 2012
[INFO] Final Memory: 7M/81M
[INFO] ------------------------------------------------------------------------

帅呆了~我们有了一个项目,然后编译他!

$ cd sample-project
$ mvn clean install

现在artifacts已经安装,让我们来跑webapp

$ cd sample-project-webapp
$ mvn jetty:run-war

现在,如果一切正确,你将在浏览器中以地址http://localhost:8080/sample-project-webapp/sample-project看到“Hello world!”


一口气翻3篇,终于翻完了,第一次翻译,艾玛累死了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值