Skip to content
Archer edited this page Jan 26, 2018 · 12 revisions

Maven Basic

Maven Coordinate

<groupId>org.sonatype.nexus</groupId>
<artifactId>nexus-indexer</artifactId>
<version>2.0.0</version>
<packaging>jar</packaging>
  • groupId - 定义当前Maven项目隶属的实际项目
  • artifactId - 定义实际项目中的一个Maven项目(模块)
  • version - 定义Maven项目 当前所处的版本
  • packaging - 定义Maven项目的打包方式,默认为jar。打包方式会影响构建的生命周期,比如jar打包和war打包会使用不同的命令。
  • classifier - 定义构建输出的一些附属构建,如javadoc.jar或者sources.jar。不能直接定义项目的classifier,因为附属构不是项目直接默认生成的,而是由附加的插件帮助生成的。 以上五个元素中,groupId、artifactId、version是必须定义的 ,packaging是可选的(默认为jar),而classifier是不能直接定义的。

Maven Dependency

<project>
...
    <dependencies>
        <dependency>
            <groupId>...<groupId>
            <artifactId>...</artifactId>
            <version>...</version>
            <type>...</type>
            <scope>...</scope>
            <optional>...</optional>
            <exclusions>
                <exculusion>
                ...
                </exculusion>
            </exclusions>
        </dependency>
        ...
    </dependencies>
    ...
</project>
  • groupId、artifactId、version - 依赖的基本坐标,对于任何一个依赖来说,基本坐标是最重要的,Maven根据坐标才能找到需要的依赖。
  • type - 依赖的类型,对应于项目坐标定义的packaging。大部分情况下,该元素不必声明,其默认值为jar。
  • scope - 依赖的范围
  • optional - 标记依赖是否可选
  • exclusions - 用来排除传递性依赖

Dependency Scope

scope compile test runtime sample
compile Y Y Y sprint-core
test - Y - JUnit
provided Y Y - servlet-api
runtime - Y Y JDBC
system Y Y - Local File

使用system的时候,必须通过systemPath显式地指定依赖文件的路径。

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

Dependency Transfer

compile test provided runtime
compile compile - - runtime
test test - - test
provided provided - provided provided
runtime runtime - - runtime

当第二依赖的范围是compile的时候,传递性依赖的范围与第一依赖的范围一致;当第二依赖的范围是test的时候,依赖不会得以传递;当第二依赖范围是provided的时候,只传递第一依赖也为provided的依赖,且传递性依赖的范围同样为provided;当第二依赖的范围是runtime的时候,传递性依赖的范围与第一依赖一致,但compile除外,此时传递性的依赖范围为runtime。

Dependency Mediation

  • First Principle - The depth of dependency works. For example, A->B->C->X(1.0), A->D->X(2.0). X(2.0) will be used as dependency.
  • Second Principle - The first statement works. For example, A->B->X(1.0), A->C->X(2.0). X(1.0) will be used as dependecy if B was declared before C.

Maven Lifecycle

clean

  • pre-clean
  • clean
  • post-clean

default

  • validate
  • initialize
  • generate-sources
  • process-sources
  • generate-resources
  • process-resources
  • compile
  • process-classes
  • generate-test-sources
  • process-test-sources
  • generate-test-resources
  • process-test-resources
  • test-compile
  • process-test-classes
  • test
  • prepare-package
  • package
  • pre-integration-test
  • integration-test
  • post-integration-test
  • verify
  • install
  • deploy

site

  • pre-site
  • site
  • post-site
  • site-deploy

Maven Properties

  • Internal Properties
    ${basedir} - Project base dir (the directory of project pom.xml)
    ${version} - Project version
  • POM Properties
    ${project.groupId} - The groupId of the project
    ${project.artifactId} - The artifactId of the project
    ${project.version} - The version of the project, equals to ${version}
    ${project.build.sourceDirectory} - The source directory of the project, src/main/java/ as default
    ${project.build.testSourceDirectory} - The test source directory of the project, test/main/java/ as default
    ${project.build.directory} - The output directory of the project build, target/ as default
    ${project.outputDirectory} - The output directory of the source compilation, target/classes/ as default
    ${project.testOutputDirectory} - The output directory of the test source compilation, target/test-classes/ as default
    ${project.build.finalName} - The output file name of the project build, ${project.artifactId}-${project.version} as default
  • Custom Properties
<project>
...
    <properties>
        <my.prop>hello-world</my.prop>
    </properties>
...
</project>

Use ${my.prop} instead of hello-world

  • Settings Properties - The usage of Settings Properties is the same as POM Properties
  • Java Properties - All Java properties can be used as maven properties. For example, ${user.home} points to user directory. Run mvn help:system to view all Java properties
  • Environment Properties - All environment properties can be used as maven properties with the start of env.. For example, ${env.JAVA_HOME} points to JAVA_HOME * environment property. Run mvn help:system to view all environment properties

Maven Profile

Activate profile:

  • command line - mvn clean install -Pdev-x,dev-y, activate dev-x and dev-y
  • settings
<settings>
...
    <activateProfiles>
        <activateProfile>dev-x</activateProfile>
        <activateProfile>dev-y</activateProfile>
    </activateProfiles>
...
</settings>
  • property - Only the property exists and has the correct value, the profile can be activated.
<profiles>
    <profile>
        <activation>
            <property>
                <name>testName</name>
                <value>x</value>
            </property>
        </activation>
    </profile>
</profiles>

User can statement a property by using -D. For example, mvn clean install -DtestName=x

  • OS environment
<profiles>
    <profile>
        <activation>
            <os>
                <name>Windows XP</name>
                <family>Windows</family>
                <arch>x64</arch>
                <version>5.1.2600</version>
            <os>
        <activation>
    <profile>
</profiles>
  • file exist
<profiles>
    <profile>
        <activation>
            <file>
                <missing>x.properties</name>
                <exists>y.properties</family>
            <file>
        <activation>
    <profile>
</profiles>
  • default
<profiles>
    <profile>
        <activation>
            <activeByDefault>true</activeByDefault>
        <activation>
    <profile>
</profiles>

If exists one profile is activated by other way, all default activated profiles will be stopped.

Maven Repository

Local Repository

<settings>
    <localRepository>D:\java\repository\</localRepository>
</settings>

Remote Repository

Configure remote repositories information in settings.xml

<settings>
...
    <profiles>
        <profile>
            <id>nexus</id>
            <repositories>
                <repository>
                    <id>nexus</id>
                    <name>Nexus</name>
                    <url>http://localhost:8081/nexus/content/groups/public/</url>
                    <releases><enabled>true</enabled></releases>
                    <snapshots><enabled>true</enabled></snapshots>
                </repository>
            </repositories>
            <pluginRepositories>
                <pluginRepository>
                    <id>nexus</id>
                    <name>Nexus</name>
                    <url>http://localhost:8081/nexus/content/groups/public/</url>
                    <releases><enabled>true</enabled></releases>
                    <snapshots><enalbed>true</enabled></snapshots>
                </pluginRepository>
            </pluginRepositories>
        </profile>
    </profiles>
    <activeProfiles>
        <activeProfile>nexus</activeProfile>
    </activeProfiles>
...
</settings>

Configure remote repositories information in pom.xml

<repositories>
    <repository>
        <id>jboss</id>
        <name>JBoss Repository</name>
        <url>http://repository.jboss.com/maven2/</url>
        <layout>default</layout>
        <releases>
            <enabled>true</enabled>
        </releases>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>

For releases and snapshots properties, two other elements were contained, which were updatePolicy and checksumPolicy

<snapshots>
    <enabled>true</enabled>
    <updatePolicy>daily</updatePolicy>
    <checksumPolicy>ignore</checksumPolicy>
</snapshots>

The property updatePolicy was used to configure the update frequency from remote repository.

  • daily - Default value. Maven update repository everyday
  • never - Maven never update repository
  • always - Maven update repository immediately when the project is built
  • interval: X - Maven update every X minutes (X can be any positive integer)

The property checksumPolicy was used to configure the policy of validations and files. If validation was failed when downloading the artifactories or building project:

  • warn - Maven will output warning information
  • fail - Maven will stop building
  • ignore - Maven will ignore the failure

Repository configuration can be configured directly in POM file, but certification can only be configured in settings.xml file.

<settings>
...
    <servers>
        <server>
            <id>my-repository</id>
            <username>repo-user</username>
            <password>repo-pwd</password>
        </server>
    </servers>
...
</settings>

The id is the key word for the relationship of certification and repository configuration.

Central Repository

Abstract POM $M2_HOME/lib/maven-model-builder-3.0.jar!/org/apache/maven/model/pom-4.0.0.xml

<repositories>
    <repository>
        <id>central</id>
        <name>Maven Repository Switchboard</name>
        <url>http://repo1.maven.org/maven2</url>
        <layout>default</layout>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>

Deploy

  1. Configure the distribution information in POM
<project>
...
    <distributionManagement>
        <repository>
            <id>project-releases</id>
            <name>Project Release Repository</name>
            <url>http://192.168.1.100/content/repositories/project-releases</url>
        </repository>
        <snapshotRepository>
            <id>project-snapshots</id>
            <name> Project Snapshot Repository</name>
            <url>http://192.168.1.100/content/repositories/project-snapshots</url>
        </snapshotRepository>
    </distributionManagement>
...
</project>
  1. Configure the certification information in settings.xml
  2. Run mvn clean deploy. If the project is snapshot version, the artifactory will be deploy to snapshot repository.

Mirrors

Configure mirrors in settings.xml to replace the central repository.

<settings>
...
    <mirrors>
        <mirror>
            <id>maven.net.cn</id>
            <name>one of the central mirrors in China</name>
            <url>http://maven.net.cn/content/groups/public</url>
            <mirrorOf>central</mirrorOf>
        </mirror>
    </mirrors>
...
</settings>

The value of mirrorOf matches the value of repository id which will be replaced. If the value of mirrorOf is *, all remote repository requests will be sent to this mirror.

  • <mirrorOf>*</mirrorOf> - Match all remote repositories
  • <mirrorOf>external:*</mirrorOf> - Match all remote repositories, but localhost excluded
  • <mirrorOf>repo1, repo2</mirrorOf> - Match repository repo1 and repo2
  • <mirrorOf>*, !repo1</mirrorOf> - Match all remote repositories, but repo1 excluded

Maven Command

Basic Commands

  • mvn -h - View mvn command help
  • mvn help:system - Print all java system properties and environemnt variables
  • mvn archetype:generate - Generate maven project archetype
  • mvn clean compile - Clean directory target/ and compile project
  • mvn clean test - Clean directory target/ and output test code report
  • mvn clean package - Clean directory target/ and package project
  • mvn clean install - Clean directory target/ and package project, then install the package to local repository
  • mvn clean deploy - Deploy project artifactory to the correct remote repository
  • mvn dependency:list - View all resolved dependencies
  • mvn dependency:tree - View all resolved dependencies as dependency tree
  • mvn dependency:analyze - Analyze the dependencies to see which dependencies were used undeclared dependencies or unused declared dependencies
  • mvn corbertura:cobertura - Generate test coverage reports
  • mvn release:prepare - Prepare release version
  • mvn release:rollback - Rollback release version
  • mvn release:perform - Perform version release
  • mvn release:branch - Release branch version
  • mvn site:stage - Generate project site

Special Command

  • mvn help:describe -Dplugin=org.apache.maven.plugins:maven-source-plugin:2.1.1 -Ddetail - View maven-source-plugin:2.1.1 detail

Command Params

  • -U - Forcely update repository. For example, mvn clean install-U
  • -D - Define a system property. For example, mvn clean install-Dmaven.test.skip=true
  • -P - Activate a profile. For example, mvn clean install -Pdev. Activate the profile with id dev
  • -am - Also make. Build projects and the dependent projects. For example, mvn clean install -am
  • -amd - Also make dependents. Build projects and the projects which are dependent on the list projects. For example, mvn clean install -amd
  • -pl - Project list [arg]. Build arg modules. For example, mvn clean install -pl project1,project2
  • -rf -Resume from [arg]. Configure the first order of the Reactor Build Order. For example, mvn clean install -rf project1
  • skipTests - Skip maven-surefire-plugin. For example, mvn package-DskpiTests
  • maven.test.skip - Skip compiling test code and run test code. For example, mvn package-Dmaven.test.skip=true
  • test - Figure out which test cases will be test. For example, mvn test-Dtest=CalculatorTest, mvn test-Dtest=Cal*Test, mvn test-Dtest=Cal*Test, App*Test
  • autoVersionSubmodules - Submodules use parent module's version automatically. For example, mvn release:prepare -DautoVersionSubmodules=true
  • performRelease - Activate in super POM. For example, mvn clean install -DperformRelease=true
  • branchName - Branch version name
  • updateBranchVersions - Update branch version or not
  • updateWorkingCopyVersions - Update trunk version or not. For example of above three, mvn release:branch -DbranchName=1.1.1 -DupdateBranchVersion=true -DupdateWorkingCopyVersion=false
  • stagingDirectory - Generate site with staging directory. For example, mvn site:stage -DstagingDirectory=D:\temp

Version Management

Maven Release Plugin

  • release:prepare - Prepare release version
  • release:rollback - Rollback relase:prepare operation
  • release:perform - Perform version release operation

Config SCM(Software Configuration Management)

<project>
...
    <scm>
        <connection>scm:svn:http://192.168.1.101/app/trunk</connection>
        <developerConnection>scm:svn:http://192.168.1.101/app/trunk</developerConnection>
        <url>http://192.168.1.101/account/trunk</url>
    </scm>
...
</project>

Config project tags and branches information

<plugin>
    <groupId>com.apache.maven.plugins</groupId>
    <artifactId>maven-release-plugin</artifactId>
    <version>2.0</version>
    <configuration>
        <tagBase>https://192.168.1.101/app/tags</tagBase>
        <branchBase>https://192.168.1.101/app/branches</branchBase>
    </configuration>
</plugin>

Maven Cases

1. 使用maven-jar-plugin和maven-dependency-plugin插件打包

<build>  
    <plugins>  
        <plugin>  
            <groupId>org.apache.maven.plugins</groupId>  
            <artifactId>maven-jar-plugin</artifactId>  
            <version>2.6</version>  
            <configuration>  
                <archive>  
                    <manifest>  
                        <addClasspath>true</addClasspath>  
                        <classpathPrefix>lib/</classpathPrefix>  
                        <mainClass>com.xxg.Main</mainClass>  
                    </manifest>  
                </archive>  
            </configuration>  
        </plugin>  
        <plugin>  
            <groupId>org.apache.maven.plugins</groupId>  
            <artifactId>maven-dependency-plugin</artifactId>  
            <version>2.10</version>  
            <executions>  
                <execution>  
                    <id>copy-dependencies</id>  
                    <phase>package</phase>  
                    <goals>  
                        <goal>copy-dependencies</goal>  
                    </goals>  
                    <configuration>  
                        <outputDirectory>${project.build.directory}/lib</outputDirectory>  
                    </configuration>  
                </execution>  
            </executions>  
        </plugin>  
    </plugins>  
</build>

maven-jar-plugin用于生成META-INF/MANIFEST.MF文件的部分内容,com.xxg.Main指定MANIFEST.MF中的Main-Class,true会在MANIFEST.MF加上Class-Path项并配置依赖包,lib/指定依赖包所在目录。 例如下面是一个通过maven-jar-plugin插件生成的MANIFEST.MF文件片段

Class-Path: lib/commons-logging-1.2.jar lib/commons-io-2.4.jar  
Main-Class: com.xxg.Main 

只是生成MANIFEST.MF文件还不够,maven-dependency-plugin插件用于将依赖包拷贝到${project.build.directory}/lib指定的位置,即lib目录下。 配置完成后,通过mvn package指令打包,会在target目录下生成jar包,并将依赖包拷贝到target/lib目录下。 指定了Main-Class,有了依赖包,那么就可以直接通过java -jar xxx.jar运行jar包。 这种方式生成jar包有个缺点,就是生成的jar包太多不便于管理,下面两种方式只生成一个jar文件,包含项目本身的代码、资源以及所有的依赖包。

2. 使用maven-assembly-plugin插件打包

<build>  
    <plugins>  
        <plugin>  
            <groupId>org.apache.maven.plugins</groupId>  
            <artifactId>maven-assembly-plugin</artifactId>  
            <version>2.5.5</version>  
            <configuration>  
                <archive>  
                    <manifest>  
                        <mainClass>com.xxg.Main</mainClass>  
                    </manifest>  
                </archive>  
                <descriptorRefs>  
                    <descriptorRef>jar-with-dependencies</descriptorRef>  
                </descriptorRefs>  
            </configuration>  
        </plugin>  
    </plugins>  
</build> 

打包方式

mvn package assembly:single

打包后会在target目录下生成一个xxx-jar-with-dependencies.jar文件,这个文件不但包含了自己项目中的代码和资源,还包含了所有依赖包的内容。所以可以直接通过java -jar来运行。 此外还可以直接通过mvn package来打包,无需assembly:single,不过需要加上一些配置

<build>  
    <plugins>  
        <plugin>  
            <groupId>org.apache.maven.plugins</groupId>  
            <artifactId>maven-assembly-plugin</artifactId>  
            <version>2.5.5</version>  
            <configuration>  
                <archive>  
                    <manifest>  
                        <mainClass>com.xxg.Main</mainClass>  
                    </manifest>  
                </archive>  
                <descriptorRefs>  
                    <descriptorRef>jar-with-dependencies</descriptorRef>  
                </descriptorRefs>  
            </configuration>  
            <executions>  
                <execution>  
                    <id>make-assembly</id>  
                    <phase>package</phase>  
                    <goals>  
                        <goal>single</goal>  
                    </goals>  
                </execution>  
            </executions>  
        </plugin>  
    </plugins>  
</build>  

其中package、single即表示在执行package打包时,执行assembly:single,所以可以直接使用mvn package打包。 不过,如果项目中用到Spring Framework,用这种方式打出来的包运行时会出错。

3. 使用maven-shade-plugin插件打包

<build>  
    <plugins>  
        <plugin>  
            <groupId>org.apache.maven.plugins</groupId>  
            <artifactId>maven-shade-plugin</artifactId>  
            <version>2.4.1</version>  
            <executions>  
                <execution>  
                    <phase>package</phase>  
                    <goals>  
                        <goal>shade</goal>  
                    </goals>  
                    <configuration>  
                        <transformers>  
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">  
                                <mainClass>com.xxg.Main</mainClass>  
                            </transformer>  
                        </transformers>  
                    </configuration>  
                </execution>  
            </executions>  
        </plugin>  
    </plugins>  
</build> 

配置完成后,执行mvn package即可打包。在target目录下会生成两个jar包,注意不是original-xxx.jar文件,而是另外一个。和maven-assembly-plugin一样,生成的jar文件包含了所有依赖,所以可以直接运行。 如果项目中用到了Spring Framework,将依赖打到一个jar包中,运行时会出现读取XML schema文件出错。原因是Spring Framework的多个jar包中包含相同的文件spring.handlers和spring.schemas,如果生成一个jar包会互相覆盖。为了避免互相影响,可以使用AppendingTransformer来对文件内容追加合并:

<build>  
    <plugins>  
        <plugin>  
            <groupId>org.apache.maven.plugins</groupId>  
            <artifactId>maven-shade-plugin</artifactId>  
            <version>2.4.1</version>  
            <executions>  
                <execution>  
                    <phase>package</phase>  
                    <goals>  
                        <goal>shade</goal>  
                    </goals>  
                    <configuration>  
                        <transformers>  
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">  
                                <mainClass>com.xxg.Main</mainClass>  
                            </transformer>  
                            <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">  
                                <resource>META-INF/spring.handlers</resource>  
                            </transformer>  
                            <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">  
                                <resource>META-INF/spring.schemas</resource>  
                            </transformer>  
                        </transformers>  
                    </configuration>  
                </execution>  
            </executions>  
        </plugin>  
    </plugins>  
</build>

Maven Resources Filtering

Apache document https://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html Use resources and filters and profiles to config different kinds of configurations.

<build>
   <resources>
    	<resource>
    	    <directory>src/main/resources</directory>
    	    <filtering>true</filtering>
    	</resource>
    </resources>
</build>
    <profiles>
    	<profile>
            <id>dev</id>
    	    <activation>
                <activeByDefault>true</activeByDefault>
    	    </activation>
    	    <build>
    		<filters>
    	            <filter>src/main/resources/dev.properties</filter>
    		</filters>
    	    </build>
    	</profile>
    	<profile>
    	    <id>test</id>
    	    <build>
    		<filters>
    		    <filter>src/main/resources/test.properties</filter>
    		</filters>
            </build>
    	</profile>
    	<profile>
    	    <id>prod</id>
    	    <build>
    	        <filters>
    		    <filter>src/main/resources/prod.properties</filter>
    	        </filters>
    	    </build>
    	</profile>
    </profiles>

Upon calling mvn clean install -Pdev for developer mode.

Web Resources Filtering

Two styles of the web application:

<profiles>
    <profile>
        <id>client-a</id>
        <properties>
            <client.log>a.jpg</client.log>
            <client.theme>red</client.theme>
        <properties>
    </profile>
    <profile>
        <id>client-b</id>
        <properties>
            <client.log>b.jpg</client.log>
            <client.theme>blue</client.theme> 
        <properties>
    </profile>
</profiles>

Filtering web resources:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.1-beta-1</version>
    <configuration>
        <webResources>
            <resource>
                <filtering>true</filtering>
                <directory>src/main/webapp</directory>
                <includes>
                    <include>**/*.css</include>
                    <include>**/*.js</include>
                </includes>
            </resource
        </webResources>
    </configuration>
</plugin>

Using <includes> tag to figure out which files are needed to be filtering. Upon calling mvn clean install -Pclient-a to build the project with client-a style.