25
Maven
Calvin edited this page 2013-11-14 01:37:15 +08:00
This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Maven已经进入成熟期,没什么大的变化了。风头会慢慢被Gradle之类的盖过去,但目前仍然是首选,因为它足够满足大部分项目的需求,而且懂的人非常多。

1.Sonatype

Maven被Sonatype主管后,中央仓库用Nexus管起来了。 用http://search.maven.org 就可以方便的找到jar。另外和Sun,Hibernate几家Repository的关系也好了,所有的jar都可以在中央库找到,不需要再同时指向多个Repository。

2.代理服务器与私服

如果机器不能直接上网,需要设定代理服务器,在maven目录的conf/settings.xml中,修改<proxies>小节。

如果连接中央服务器较慢,或者有项目内需要共享jar包,建议搭建一台私服,将下载后的包缓存起来供其他同事使用,私服选Nexus就很好。搭完私服后,可以在pom.xml里的<repositories>和<pluginRepositories>中增加私服定义。(参见springside-parent),也可以直接修改Maven的settings.xml的 <mirrors>小节。

##3. 版本选择与Enforcer插件 如果有多个项目都依赖了同一个依赖项,最终选择的版本并不是想当然的最高版本,历史因由是刚开始时大家的版本命名并不规范,单纯按数字/字母排序不一定对。所以,它选择了最近和最先原则。

  • 最近原则: 如果A依赖B依赖C依赖D-2.0,同时A依赖E依赖D-1.0,此时D-1.0被选择,因为依赖路径更近。

  • 最先原则: 如果大家依赖路径一样长,在pom.xml文件里位置靠前的那个赢。

    maven的魅力与麻烦之一就是依赖和依赖的依赖,有时候一不小心就会因为隐性依赖一些不想依赖的库,比如用了slf4j就不想再出现commons-logging, 比如新版aspectj的groupId已经从aspejct改为org.aspectj了, enforcer插件可以提醒你这些隐性依赖,例子可见quickstart或parent的pom.xml。

    另外,enforecer插件里定义<requireUpperBoundDeps/>,能保证最后选择最高的版本,而不是上面所谓的最近最先原则。

    另外,为免意外惊喜不断,quickstart里还用enforcer插件硬性规定了至少JDK6和Maven 3.0.3以上。

4.测试

###4.1 区分单元测试与集成测试###

原本Maven一直没有很好的区分单元测试和集成测试的用例。因为集成用例的依赖可能很多,执行又慢,很多时候我们都要Skip掉它们只运行单元测试。

后来Maven在原来的surefire插件继续负责在test阶段测试Test.java的单元测试用例, 新增了failsafe插件负责在integration-test阶段(package阶段之后)执行IT.java的集成测试。

但SpringSide在SpringSide4.0 RC2之后不再使用这个插件,首先因为springside是使用嵌入式Jetty,Out-Of-Container的执行功能测试用例的,所以在集成测试阶段之前的Package阶段打war包是白做的。其次继续把*IT.java用例继续放在test/java里,使得在Eclipse没有办法单独执行所有的单元测试。(因为Eclipse没有办法执行某个子目录及其子子目录下的所有用例)

所以SpringSide的综合解决办法是,用codehaus的build-helper-maven-plugin插件新开一个Functional Test Source 目录test/functional,将所有功能测试用例放到这里,然后文件名采用FT.java后缀,然后建不同的Profile,执行Test.java 或*FT.java.

在两个Examples项目的pom.xml中都有完整的示例,在eclipse:eclipse或m2e插件生成的项目文件里,都会包含新开的functional源码目录。

###4.2 Skip Test###

mvn install -Dmaven.test.skip=true 最狠的,连测试用例的编译都省掉了。

###4.3 分组执行###

TestNG的皇牌功能,可以将用例分成几组,比如超慢的Nightly组放到半夜才运行。 Junit4后来的新版也支持一个@Category的定义,但是,必须在一个TestSuite维护所有Case,或者使用一个叫ClassPathSuite的项目。

在Maven的测试插件里没这个麻烦,它会自行读取@Category标签来过滤。

pom.xml

    <plugin>
      <artifactId>maven-surefire-plugin</artifactId>
      <version>2.12</version>
      <configuration>
        <groups>com.mycompany.FastTests</groups>
      </configuration>
      <dependencies>
        <dependency>
	  <groupId>org.apache.maven.surefire</groupId>
	  <artifactId>surefire-junit47</artifactId>
	  <version>2.12</version>
	</dependency>
      </dependencies>
    </plugin>

TestCase中的testSlow()将不会被执行。

    public class AppTest {
      @Test
      @Category(SlowTests.class)
      public void testSlow() {
        System.out.println("slow");
      }

      @Test
      @Category(FastTests.class)
      public void testFast() {
        System.out.println("fast");
      }
    }

###4.4 透传命令行的参数到测试插件 测试插件是自己Fork一个JVM出来的,所以启动Maven时的系统参数不会直接透传到测试中,比如我想在命令行控制selenium.driver,需要这样配置

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-failsafe-plugin</artifactId>
	<configuration>
		<systemPropertyVariables>
			<selenium.driver>${selenium.driver}</selenium.driver>
		</systemPropertyVariables>
	</configuration>
</plugin>

##5.脚本?脚本!! 虽然Maven的理想很丰满,什么都是插件,什么都是阶段,但实际项目还是有很多需要脚本干点小事情的时候,比如springside里更新本地测试数据库。这时候有两种选择,一种是完全用ant脚本,需要依赖包的时候用ant的maven插件,另一种是在maven里用antrun插件。

因为ant的maven插件老是被忘记下载,所以springside里选择了用maven的antrun插件,另外也不搞什么阶段了,定义出独立的profile,直接运行goal: mvn antrun:run -Prefresh-db

另外,exec:java来运行Java命令也不错。

##6. Maven与Eclipse的集成 详见Maven2Eclipse 插件。

##7. Archetype插件生成项目 详见基于SpringSide创建项目

##8. 依赖及插件更新通知

  • mvn versions:display-dependency-update 可显示 依赖更新
  • mvn versions:display-plugin-update 可显示 插件更新

多模块时,在parent的pom文件处运行上述命令。

pom文件里需有这句, 插件更新的显示才靠谱。

<prerequisites>
    <maven>2.2.1</maven>
</prerequisites>

插件更新通知看邮件列表: http://mail-archives.apache.org/mod_mbox/maven-announce/

##9. Assembly插件 Maven的万能打包插件,可以除了标准的jar/war外,打包自己的发布包。在showcase中演示了如何打包一个可执行的War包。

资料