持续集成自动化的第二种实现方式思路:以开发工具生成的项目(或者开发者自己规定的目录结构)为核心,调整Maven的POM配置文件,用于项目开发和CI构建。
一、基本步骤
1、准备阶段
1.1. 通过Eclipse生成项目,并结合自身需求修订项目结构,以用于构建(工作空间)
1.2. 生成POM.xml文件,设置各类目录配置
1.3. 通过SVN生成空的、新的版本控制仓库
1.4. 向SVN 提交(import) Eclipse工程项目中的源代码目录和相关文件,形成开发用的源代码仓库
1.5. 通过Jenkins整合源代码仓库和Maven构建工程
2、使用阶段
2.1. 下载仓库里的源代码
2.2. 提交更新后的源代码
2.3. 自动进行构建工作
与第一种方式相比较,主要是定义项目目录结构(步骤1.1和1.2)的操作不一样。步骤1.4中只是换了源代码的来源而已,而具体操作方法与学习笔记(5)中所讲的是一样的。所以本文只叙述1.1和1.2,其余的操作可以参考学习笔记(5)。这一方法需要对pom.xml投入更多的精力,但比较灵活。
二、具体实现
1、准备阶段
1.1. 通过Eclipse生成项目,并结合自身需求修订项目结构,以用于构建(工作空间)
(1) 通过Eclipse生成一个java project,其目录结构如下:
(2)根据项目需求,添加相关的目录。为了进行试验,笔者故意将目录结构写的与maven默认的不同。添加后形成的目录结构如下:
其中,各目录的用途说明如下
demo2
|-- bin //主程序所需的jar文件所在目录,例如jdbc驱动。
|-- src //主程序源代码所在目录
|-- test //test源代码所在目录
| |-- resources //test所需资源文件目录
|
|-- resources //主程序所需资源文件目录。
`-- mytarget //编译、打包后的.jar文件所在目录
|-- classes //主程序源代码编译后的.class文件所在目录
|-- test-classes //test代码编译后的.class文件所在目录
另外,为测试构建结果,笔者事先放置了几个文件:
l /bin下放置了111.txt
l /resources下放置了333.txt
l /src 放置了Helloworld.java文件
l /test/resources下放置了222.txt
同时,mytarget下也可以不事先设置classes和test-classes两个目录。只要在POM.xml指明主程序和test源代码的OutputDirectory,这两个目录就可以在构建过程中自动生成。
1.2. 生成POM.xml文件
可以通过记事本或其他编辑工具生成一个空白内容的POM.xml文件,或者通过Eclipse生成。如图所示,笔者通过Eclipse生成POM.xml文件。由于生成步骤比较简单,所以就不再详述具体过程了。
将生成后的POM.xml文件放至demo2的根目录下。这样,本示例形成的目录文件夹就可以作为CI的工作空间了。而用于开发的目录文件夹可仿照学习笔记(5)中另外建立。
通过在pom.xml中明确地指出目录结构,用以覆盖Maven的默认目录结构。
(1)自定义目录结构的主要类别
1、主程序源代码的来源目录和生成class文件的目标目录
2、测试用例代码的来源目录和生成class文件的目标目录
3、程序使用的其他资源文件(如图片、CSS、jar文件等)的来源目录
(2)目录之间编译打包的关系和顺序
l Java的主程序源代码、测试用例代码都需要经过编译(cimpiler)过程,才会把生成后的.class文件放到目标目录中。
l Test的相关.class文件不会被打包,只用于构建过程中的测试。
l 打包进jar文件的内容包括:
Ø Java的主程序生成的.class文件;
Ø 资源(resource)文件则是直接复制到打包文件里的。
(3)pom.xml内容
针对示例,笔者在pom.xml添加的代码和注释如下:
<!—POM的一些基本说明-->
<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>demo2</groupId>
<artifactId>demo2</artifactId>
<version>1.0-SNAPSHOT</version>
<!--加入junit依赖,用于单元测试-->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<!-- 这是打包文件的目标目录。生成的ourdemo.jar文件会放到demo2/ mytarget目录下。这种目录是相对路径。如果打算把结果放置到工程目录之外,也可以添加绝对路径,比如”D:/myweb/ mytarget”-->
<directory> mytarget </directory>
<!-- 生成的jar目标文件名称 -->
<finalName>ourdemo</finalName>
<!--加入compiler-plugin,用于对java代码的编译-->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.4</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
<!--主程序源代码的来源目录 -->
<sourceDirectory>src</sourceDirectory>
<!-- 编译后的.class文件所在的目标目录 -->
<outputDirectory>mytarget/classes</outputDirectory>
<!-- 测试用例代码的来源目录。在打包.jar文件时,这些源代码不会被打包到jar里-->
<testSourceDirectory>test</testSourceDirectory>
<testOutputDirectory>mytarget/test-classes</testOutputDirectory>
<!-- 资源文件存放目录。这些目录下的文件不需要编译,文件(不含目录本身)直接复制到jar包里。若resources 下还有子目录,则连子目录和子目录下的文件一块复制-->
<resources>
<resource>
<directory>resources</directory>
<!--例外的文件类型。如果这里存放有.java文件,则仍然需要编译-->
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
<resource>
<directory>bin</directory>
</resource>
</resources>
<!--在打包.jar文件时,test文件夹下的源代码和资源文件都不会被打到jar包里面-->
<testResources>
<testResource>
<directory>test/resources </directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</testResource>
</testResources>
</build>
</project>
然后可以根据构建需求,增加相关的dependency和plugin内容。
2、构建结果
通过Jenkins建立相应的job(或通过Eclipse直接执行 mvn install命令),笔者给其起名为demo2。进行构建后,看一下在mytarget目录下的生成结果情况。
可以看到,在mytarget目录下,生成了ourdemo.jar文件。其中,surefire和maven-archiver到底是干什么,请各位自行研究吧。我们把ourdemo.jar解压缩,然后再看一下目录结构
我们看到,主程序源代码生成的class文件,/bin下的111.txt,/resources下的333.txt都被纳入jar文件中,而用于测试的/test/resources下的222.txt则没有被放入(它被放到\mytarget\test-classe目录了)。
至于META-INF目录,里面主要是本示例所用的POM.xml和与maven构建相关的其他一些文件。