[软件过程] JAVA 持续继承 (HUDON MAVEN 多模块实践)

现在IT界最流行的莫过于 敏捷 。本人有幸实践了下敏捷的几个原则,其中一个重要的原则就是持续集成(consistent integration = CI):它能带给我们以下几个好处:

  1. 高质量的代码。
  2. 让重构没有后顾之忧。
  3. 在没有产品的时候,持续集成的数据能让你有信心。

那么什么是持续集成呢?是不是就是跑单元测试呢?

在我几个月的实践和摸索中,我觉得跑单元测试,代码风格工具(check-style)以及代码质量检查工具(FINDBUGS 、PMD等)都是持续集成的表象或者说是手段。持续集成的目的是为了让分散的代码有机的结合起来,并能运行起来,一步一步滚雪球才达到最后的产品。

 

言归正传,我们先来看下有哪些CI 工具:

  1. Cruise Control
  2. Continuum
  3. Luntbuild
  4. Hudson

以上的几个我也只用过 Cruise Control 和 Hudson,这两者也很相似,不过后者开源

对与更详细的简介,还是看国外的高手写的对比吧 : 点击这里

 

这里我先介绍下HUDSON 吧。

HUDSON 的架构采取了插件的形式,也就是说一些工具(PMD等)是以插件的形式起作用的,这样带给HUDSON很大的灵活性。

我选择HUDSON的原因还有一个就是他小,只有一个20+的war包,部署十分方便:只要放到web容器下(比如tomcat的webapp下) 使用 http://localhost:8081就可以访问了,其余的设置操作均可以可视化。还值得一提的是HUDSON原生就支持MAVEN

 

接下来的例子将是一个有多工程的项目结构,并使用了 findbugs 、pmd、check-style、cobertura等工具。

 

先来看下主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>org.ray</groupId>


  <artifactId>tb.crm.all</artifactId>


  <packaging>pom</packaging>


  <version>1.0</version>





  <name>tb.crm.all</name>





  <properties>


    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>


    <reportdir>${basedir}/../report</reportdir>


    <jdk>1.6</jdk>


  </properties>





  <modules>


	<module>tb.crm.utils</module>


	<module>tb.crm.framework</module>


	<module>tb.crm.datalayer</module>


	<module>tb.crm.datamining</module>


	<module>tb.crm.app</module>


	<module>tb.crm.war</module>


  </modules>





  <dependencyManagement>


	<dependencies>


	<dependency>


		<groupId>${project.groupId}</groupId>


		<artifactId>tb.crm.framework</artifactId>


		<version>${project.version}</version>


	</dependency>


	


	<dependency>


		<groupId>${project.groupId}</groupId>


		<artifactId>tb.crm.utils</artifactId>


		<version>${project.version}</version>


	</dependency>


	


	<dependency>


		<groupId>${project.groupId}</groupId>


		<artifactId>tb.crm.datalayer</artifactId>


		<version>${project.version}</version>


	</dependency>





	<dependency>


		<groupId>${project.groupId}</groupId>


		<artifactId>tb.crm.datamining</artifactId>


		<version>${project.version}</version>


	</dependency>





	<dependency>


		<groupId>${project.groupId}</groupId>


		<artifactId>tb.crm.app</artifactId>


		<version>${project.version}</version>


	</dependency>





	<dependency>


		<groupId>${project.groupId}</groupId>


		<artifactId>tb.crm.war</artifactId>


		<version>${project.version}</version>


	</dependency>


<!-- end of project modules-->





	<dependency>


		<groupId>com.taobao.api</groupId>


		<artifactId>taobao-base</artifactId>


		<version>2.0-SNAPSHOT</version>


	</dependency>





<!-- end of taobao api denpendency -->


	<dependency>


		<groupId>org.apache.struts</groupId>


		<artifactId>struts2-core</artifactId>


		<version>2.1.8.1</version>


	</dependency>





	<dependency>


    	<groupId>org.apache.struts</groupId>


    	<artifactId>struts2-spring-plugin</artifactId>


    	<version>2.1.8</version>


	</dependency>





	<dependency>


    	<groupId>org.apache.ibatis</groupId>


    	<artifactId>ibatis-sqlmap</artifactId>


    	<version>2.3.4.726</version>


	</dependency>





    <dependency>


       	<groupId>log4j</groupId>


        <artifactId>log4j</artifactId>


       	<version>1.2.14</version>


    </dependency>





    <dependency>


       	<groupId>org.springframework</groupId>


        <artifactId>spring-orm</artifactId>


       	<version>2.5.6</version>


    </dependency>





    <dependency>


       	<groupId>org.springframework</groupId>


        <artifactId>spring-jdbc</artifactId>


       	<version>2.5.6</version>


    </dependency>





    <dependency>


       	<groupId>junit</groupId>


        <artifactId>junit</artifactId>


       	<version>4.4</version>


    </dependency>





	<dependency>


    	<groupId>mysql</groupId>


    	<artifactId>mysql-connector-java</artifactId>


    	<version>5.1.12</version>


	</dependency>





	<dependency>


    	<groupId>commons-dbcp</groupId>


    	<artifactId>commons-dbcp</artifactId>


    	<version>1.4</version>


	</dependency>





	<dependency>


    	<groupId>commons-lang</groupId>


    	<artifactId>commons-lang</artifactId>


    	<version>2.5</version>


	</dependency>





	<dependency>


    	<groupId>commons-collections</groupId>


    	<artifactId>commons-collections</artifactId>


    	<version>3.2.1</version>


	</dependency>


	</dependencies>





  </dependencyManagement>





  <build>


<!-- project plugins-->


   <pluginManagement>


	<plugins>


		<plugin>


			<groupId>org.apache.maven.plugins</groupId>


			<artifactId>maven-war-plugin</artifactId>


			<version>2.1-beta-1</version>


		</plugin>





		<plugin>


          <groupId>org.apache.maven.plugins</groupId>


		  <artifactId>maven-source-plugin</artifactId>


		  <executions>


				 <execution>


	                 <id>attach-source</id>


                     <goals>


						<goal>jar</goal>


					 </goals>


				 </execution>


		  </executions>


		</plugin>





        <plugin>


                <groupId>org.apache.maven.plugins</groupId>


                <artifactId>maven-eclipse-plugin</artifactId>


				<version>2.8</version>


                <configuration>


                    <downloadSources>true</downloadSources>


                    <downloadJavadocs>true</downloadJavadocs>


                </configuration>


      </plugin>





	  <plugin>


        <groupId>org.apache.maven.plugins</groupId>


        <artifactId>maven-compiler-plugin</artifactId>


        <version>2.2</version>


        <configuration>


          <source>${jdk}</source>


          <target>${jdk}</target>


        </configuration>


      </plugin>





      <plugin>


        <groupId>org.apache.maven.plugins</groupId>


        <artifactId>maven-pmd-plugin</artifactId>


        <version>2.3</version>


		<executions>


			<execution>


				<phase>install</phase>


				<goals>


					<goal>pmd</goal>


				</goals>


			</execution>


		</executions>


		<configuration>


			<source>${jdk}</source>


			<targetJdk>${jdk}</targetJdk>


         	<rulesets>


            	<ruleset>/rulesets/braces.xml</ruleset>


            	<ruleset>/rulesets/strings.xml</ruleset>


            	<ruleset>/rulesets/naming.xml</ruleset>


			</rulesets>


		</configuration>


      </plugin>





      <plugin>


        <groupId>org.codehaus.mojo</groupId>


        <artifactId>findbugs-maven-plugin</artifactId>


        <version>2.0.1</version>


		<executions>


			<execution>


				<phase>install</phase>


				<goals>


					<goal>findbugs</goal>


				</goals>


			</execution>


		</executions>


      </plugin>





      <plugin>


        <groupId>org.apache.maven.plugins</groupId>


        <artifactId>maven-checkstyle-plugin</artifactId>


        <version>2.5</version>


		<executions>


			<execution>


				<phase>install</phase>


				<goals>


					<goal>checkstyle</goal>


				</goals>


			</execution>


		</executions>


		<configuration>


			<enableRulesSummary>true</enableRulesSummary>


			<configLocation>${reportdir}/checkstyle.xml</configLocation>


		</configuration>


      </plugin>


      


	  <plugin>


        <groupId>org.codehaus.mojo</groupId>


        <artifactId>cobertura-maven-plugin</artifactId>


        <version>2.4</version>


		<configuration>


			<formats>


				<format>xml</format>


			</formats>


			<instrumentation>


				<ignores>


					<ignore>org.ray.demo.*</ignore>


				</ignores>


			</instrumentation>


		</configuration>


		<executions>


			<execution>


				<phase>install</phase>


				<goals>


					<goal>clean</goal>


					<goal>cobertura</goal>


				</goals>


			</execution>


		</executions>


      </plugin>





	</plugins>


   </pluginManagement>


   


	<plugins>


	  <plugin>


        <groupId>org.apache.maven.plugins</groupId>


        <artifactId>maven-compiler-plugin</artifactId>


	  </plugin>





	  <plugin>


          <groupId>org.apache.maven.plugins</groupId>


		  <artifactId>maven-source-plugin</artifactId>


	  </plugin>





    	<plugin>


       		 <groupId>org.apache.maven.plugins</groupId>


       		 <artifactId>maven-checkstyle-plugin</artifactId>


     	 </plugin>


 


     <plugin>


        <groupId>org.apache.maven.plugins</groupId>


        <artifactId>maven-pmd-plugin</artifactId>


	 </plugin>





      <plugin>


        <groupId>org.codehaus.mojo</groupId>


        <artifactId>findbugs-maven-plugin</artifactId>


		</plugin>


	  


	<plugin>


        <groupId>org.codehaus.mojo</groupId>


        <artifactId>cobertura-maven-plugin</artifactId>


	</plugin>


	</plugins>


  </build>


</project>


 

主要是红色的配置,这样HUDSON才能找到必要的文件。(想要高阶设置的话,还是需要配合HUDSON配置)。子工程并不需要做任何配置,所以代码就不贴出了。

 

然后是HUDSON的配置:

首先我们要部署好HUDSON,也就是放到tomcat容器下,或者用命令:

java -jar hudson.war

 然后我们使用 http://localhost:8081访问控制台:

[软件过程] JAVA 持续继承 (HUDON MAVEN 多模块实践)

 

在Manage Hudson > Configure  System 的选项卡里面我们可以设置登录的帐号等系统配置。

 

然后我们新建一个job 每个job表示一个工程,然而HUDSON是支持工程依赖的,也就是说我们有AB两个工程,A工程的构建如果依赖B工程的构建,那么可以定制这种关系,让HUDSON在B构建完成后才取构建工程。

 

为了达到我们要的目的,我们先在 Manage Hudson > Manage Plugins 选项卡中安装我们想要的插件:

findbugs 、pmd、check-style、cobertura

[软件过程] JAVA 持续继承 (HUDON MAVEN 多模块实践)

 

 

然后我们要在刚才新建的${job} > Configure 选项卡中配置信息:

如果有任何疑问可以点击后面的问号,会有详细的提示。

[软件过程] JAVA 持续继承 (HUDON MAVEN 多模块实践)

 

[软件过程] JAVA 持续继承 (HUDON MAVEN 多模块实践)

 

这里还值得一提的是 HUDSON有健康机制,也就是说当你为某个plugin设置了一个阀值,当超过这个阀值的时候,这个项目的健康状况会变差,并且以图标表示出来。


而且有FF 、ECLIPSE 、IPHONE 插件用来显示这个健康状况,比如我用的是FF插件的效果图:

[软件过程] JAVA 持续继承 (HUDON MAVEN 多模块实践)

绿色的点就是我项目的健康状况,后面的文字是项目名称。

 

好了,大致使用流程就是这样子。还是很好用的萨。