Maven

Maven

 

<?xml version=”1.0” encoding=”utf-8” ?>
<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.0http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.juvenxu.mvnbook</groupId>
    <artifactId>hello-world<artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>Maven Hello World Project</name>
</project>

modelVersion指定了当前POM模型的版本,对于Maven2和3来说,他只能是4.0.0。

groupId定义了项目属于哪个组,这个组往往会和项目所在的组织或公司存在关联。

artifactId定义了当前Maven项目在组中唯一的ID。

version指定了Hello World项目当前的版本。

name元素声明了一个对于用户更为友好的项目名称。

 

HTTP代理

<settings>
    <proxy>
        <id>my-proxy</id>
        <active>true</active>
        <protocol>http</protocol>
        <host>192.168.168.1</host>
        <port>3122</port>
        <!--
        <username>username</username>
        <password>password</password>
        <nonProxyHosts>my.site.com|*.google.com</nonProxyHosts>
        -->
    </proxy>
</settings>

 

编写主代码

在绝大多数情况下,应该把项目代码放到src/main/java目录下,而无需额外的配置,Maven会自动找到项目主代码。使用Maven进行编译,在项目根目录下运行命令mvn clean compile

 

编写测试代码

Maven项目中默认的测试代码目录是src/test/java。在编写测试用例之前应当先创建该目录。

<project>
    <dependencies>
       <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>4.7</version>
           <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
       <plugins>
           <plugin>
              <groupId>com.apache.maven.plugins</groupId>
              <artifactId>maven-compiler-plugin</artifactId>
              <configuration>
                  <source>1.5</source>
                  <target>1.5</target>
              </configuration>
           </plugin>
       </plugins>
    </build>
</project> 

代码中添加了dependencies元素,该元素下可以包含多个dependency元素以声明项目的依赖。

元素scope为依赖范围,若依赖范围为test则表示该依赖只对测试有效。

 

Maven的核心插件compiler插件默认只支持编译Java1.3,因此需要配置该插件使其支持1.5。

执行mvn clean test

 

打包和运行

将项目进行编译、测试之后,下一个重要步骤就是打包。默认打包类型为jar。执行命令mvn clean package打包。

 

默认打包生成的jar是不能够直接运行的,因为带有main方法的类信息不会添加到manifest中。为了生成可执行的jar文件,需要借助maven-shade-plugin,配置该插件如下

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin<artifactId>
    <version>1.2.1</version>

    <executions>
       <execution>
           <phase>package</phase>
            <goals>
               <goal>shade</goal>
           </goals>
           <configuration>
              <transformers>
                  <transformer implementation="org.apache.maven.plugins.shade.resource.MainfestResourceTransformer">
                     <mainClass>com.juvenxu.mvnbook.helloworld.HelloWorld</mainClass>
                  </transformer>
              </transformers>
           </configuration> 
       </execution>
    </executions>
</plugin>

 

使用Archetype生成项目骨架

mvn archetype:generate

 

Eclipse

maven-archetype-quickstart

 

 

坐标和依赖

 

坐标详解

<groupId>org.sonatype.nexus</groupId>
<artifactId>nexus-indexer<artifactId>
<version>2.0.0</version>
<packaging>jar</packaging>

groupId 定义当前Maven项目隶属的实际项目。

artifactId 该元素定义实际项目中的一个Maven项目(模块),推荐的做法是使用实际项目名称作为artifactId的前缀。

version 该元素定义Maven项目当前所处的版本。

packaging 该元素定义Maven项目的打包方式。

classifier 该元素用来帮助定义构建输出的一些附属构件。

 

依赖的配置

<project>
    <dependencies>
       <dependency>
           <groupId></groupId>
           <artifactId></artifactId>
           <version></version>
           <type></type>
           <scope></scope>
           <optional></optional>
           <exclusions></exclusions>
       </dependency>
    </dependencies>
<project>

groupId,artifactId,version 依赖的基本坐标

type依赖的类型

scope 依赖的范围

optional 标记依赖是否可选

exclusions 用来排除传递性依赖

 

依赖范围

依赖范围就是用来控制依赖与这三种classpath(编译、测试、运行)的关系,Maven有以下几种依赖范围

compile:编译依赖范围。如未指定就会默认使用该依赖范围。对于编译、测试、运行三种classpatch都有效。(spring-core)

test:测试依赖的范围。使用此依赖范围的Maven依赖,只对测试classpath有效,在编译主代码或者运行项目的使用时将无法使用。(JUnit)

provided:已提供依赖范围。使用此依赖的Maven依赖,对于编译和测试classpath有效,但在运行时无效。(servlet-api)

runtime:运行时依赖范围。使用此依赖范围的Maven依赖,对于测试和运行classpath有效,但在编译主代码时无效。(JDBC)

system:系统依赖范围。该依赖与三种classpath的关系,和provided依赖范围完全一致。但是,使用system范围的依赖时必须通过systemPath元素显式地指定依赖文件的路径。

<dependency>
    <groupId>javax.sql</groupId>
    <artifactId>jdbc-stdext</artifactId>
    <version>2.0</version>
    <scope>system</scope>
    <stystemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>

 

传递性依赖

account-email ->  spring-core -> commons-logging

account-mail有一个compile范围的spring-core依赖,spring-core有一个compile范围的commons-logging依赖,那么commons-logging就会成为account-email的compile范围依赖,common-logging是account-email的一个传递性依赖。

 

传递性依赖和依赖范围

             compile        test        provided        runtime

_________________________________________________________________

compile      compile        ----         ----           runtime

_________________________________________________________________

test         test           ----         ----           test

_________________________________________________________________

privided     privided       ----         ----           privided

_________________________________________________________________

runtime      runtime        ----         ----           runtime

_________________________________________________________________

 

依赖调解

第一条原则:路径最近者优先。(X1的路径长度为3,而路径X2的长度为2,X2会被解析使用)

第二条原则:第一声明者优先。(在依赖路径长度相等的前提下,在POM中依赖声明中最靠前的依赖优胜)

 

可选依赖

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.juvenxu.mvnbook</groupId>
    <artifactId>project-b</artifactId>
    <version>1.0.0</version>

    <dependencies>
       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <version>5.1.10</version>
           <optional>true</optional>
       </dependency>

       <dependency>
           <groupId>postgresql</groupId>
           <artifactId>postgresql</artifactId>
           <version>8.4-701.jdbc3</version>
           <optional>true</optional>
       </dependency>
    </dependencies>
</project>

使用<optional>元素表示mysql-connector-java和postgresql这两个以来为可选依赖,他们只会对当前项目B产生影响,但其他项目依赖于B的时候,这两个依赖不会被传递。因此,当项目A依赖于项目B的时候,如果其实际使用基于MySql数据库,那个在项目A中就需要显示地声明mysql-connector-java这一依赖。

 

最佳实践

 

仓库

 

 

版本管理

1.3.4-beta-2

<主版本>.<次版本>.<增量版本>-<里程碑版本>

 

<project>
  <scm>
    <connection>scm:svn:http://192.168.1.11/app/trunk</connection>
    <developerConnection>scm:svn:https://192.168.1.11/app/trunk</developerConnection>     <url>http://192.168.1.11/account/trunk</url>   </scm> <project>

connection元素表示一个只读的scm地址

developerConnection元素表示可写的scm地址

url表示可以在浏览器中访问的scm地址

 

Maven Release Plugin

release:prepare  准备版本发布

release:rollback 回退release所执行的操作

release:perform  执行版本发布

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-release-plugin</actifactId>
  <version>2.0</version>
  <configuration>
      <tagBase>https://192.168.1.11/app/tags/</tagBase>
    <branchBase>https://192.168.181.11/app/branches/</branchBase>
  </configuration>
</plugin>

使用如下命令,maven-release-plugin就会自动为所有子模块使用与父模块一致的发布版本和新的SPANSHOT版本

$mvn release:prepare –DautoVersionSubmodules=true;

 

自动化创建分支

$mvn release:branch –DbranchName=1.1.x –DupdateBranchVersions=true –DupdateWorkingCopyVersion=false

-DbranchName=1.1.x用来配置所要创建的分支的名称

-DupdateBranchVersions=true 表示为分支使用的新版本

-DupdateWorkingCopyVersions=false 表示不更新本地代码

 

Maven属性

通过<properties>元素用户可以自定义一个或多个Maven属性,然后在POM的其他地方使用${属性名称}的方式引用该属性。

 

内置属性

  • ${basedir} 表示项目根目录(pom文件的目录)
  • ${version} 标示项目版本

 

POM属性

  • ${project.build.sourceDirectory} 项目的主源码目录(src/main/java/)
  • ${project.build.testSourceDirectory} 项目的测试源码目录(src/test/java/)
  • ${project.build.directory} 项目构建输出目(target/)
  • ${project.outputDirectory} 项目主代码编译输出目录(target/classes)
  • ${project.testOutputDir} 项目测试代码编译输出目录(target/testclasses)
  • ${project.groupId} 项目的groupId
  • ${project.artifactId} 项目的artifactId
  • ${project.version} 项目的version(${version})
  • ${project.build.finalName} 项目打包输出文件名称(${project.artifactId}-${project.version})

 

Settings属性

${settings.localRepository}

以settings.开头的属性引用settings.xml文件中XML元素的值。

 

Java系统属性

${user.home}

Java系统属性都可以使用Maven属性引用(mvn help:system)。

 

环境变量属性

${env.JAVA_HOME}

环境变量都可以使用以env.开头的Maven属性引用。

 

资源过滤

database.jdbc.driverClass = ${db.driver}
database.jdbc.connectionURL = ${db.url}
database.jdbc.username = ${db.username}
database.jdbc.password = ${db.password}

 

数据库配置文件设置

<profiles>
  <profile>
    <id>main-db-config</id>
       <properties>
           <db.driver>mysql.jdbc.Driver</db.driver>
           <db.url>jdbc:mysql://localhost:3306/test<db.url>
           <db.username>root<db.username>
           <db.password>root-pwd<db.password>
    </properties>
  </profile>
  <profile>
    <id>test-db-config</id>
    <properties>
           <db.driver>mysql.jdbc.Driver</db.driver>
           <db.url>jdbc:mysql://192.168.1.11:3306/test<db.url>
           <db.username>test<db.username>
           <db.password>test-pwd<db.password>
       </properties>
    </profile>
</profiles>

maven-resources-plugin默认只是将项目主资源文件复制到主代码编译输出目录中,测试资源文件复制到测试代码编译输出目录中。

 

为主资源目录开启过滤

<resources>
    <resource>
       <directory>${project.basedir}/src/main/resource</directory>
       <filtering>true</filtering>
  </resource>  
</resources>

 

为测试资源目录开启过滤

<testResources>
    <testResource>
    <directory>${project.basedir}/src/test/resource</directory>
    <filtering>true</filtering>
    </testResource>
</testResources>

 

激活profile

 

1 命令行激活

用户可以使用mvn命令行参数-P加上profile的id来激活profile,多个id之间用逗号间隔。

$mvn clean install –Pdev–x,dev-y

 

2 settings文件显式激活

<settings>
  <activeProfiles>
    <activeProfile>dev-x</activeProfile>
  </activeProfiles>
</settings>

 

某系统属性存在且值确定时激活profile

<profiles>
    <profile>
       <activation>
           <property>
              <name>test</name>
              <value>x</value>
           </property>
       </activation>
    </profile>
</profiles>

 

命令行生命系统属性

$mvn clean install –Dtest=x

 

默认激活

<profiles>
    <profile>
       <activation>
           <activeByDefautl>true</activeByDefault>
       </activation>
    </profile>
</profiles>

如果POM中有任何一个profile通过以上其他任意一种方式被激活了,所有的默认激活配置都会失效。

 

列出当前激活的profile

$mvn help:active-profiles

列出所有的profile

$mvn help:all-profile

 

POMprofile可使用的元素

<project>
    <repositories>
    <pluginRepositories>
    <distributionManagement>
    <dependencies>
    <dependencyManagement>
  <modules>
  <properties>
  <reporting>
  <build>
        <plugins>
        <defaultGoal></defaultGoal>
        <resources>
        <testResources>
        <finalName>
  </build>
</project>

 

profile激活集成测试

TestNG中分组测试标记

@Test(groups = {“unit”})
@Test(groups = {“integration”})

在profile中配置执行TestNG测试组

<profiles>
    <profile>
       <id>full-test</id>
       <build>
           <plugins>
              <plugin>
                  <groupId>org.apache.maven.plugins<groupId>
                  <artifactId>maven-surefire-plugin<artifactId>
                  <version>2.5<version>
                  <configuration>
                     <groups>unit,integration</groups>
                  </configuration>
              </plugin>
           </plugins>
       </build>
    </profile>
</profiles>

默认Maven只会执行单元测试。如果想要执行集成测试,就需要激活full-test profile,在这个profile中配置了maven-surefire-plugin执行unit和integration两个测试组。

 

posted @ 2012-11-18 22:11  rilley  阅读(1268)  评论(0编辑  收藏  举报