Maven HowTo

Table of Contents

1 maven 简介

我们先不谈maven是什么,我们先说,我们开发一个应用需要什么

  • 编译,测试,运行,打包
  • 管理依赖
  • 项目报告

好的,maven以统一的形式提供了这些功能,虽然几乎所有功能都是以插件的形式提供的。

2 安装 maven

安装很简单,下载源码,解压,把bin目录添加到 PATH 路径即可。

# mvn -version
Apache Maven 3.3.3 (7994120775791599e205a5524ec3e0dfe41d4a06; 2015-04-22T19:57:37+08:00)

能正确运行,说明安装成功

3 修改maven源

maven的默认源在国内很慢,在 $MAVEN_HOME/conf/settings.xmlmirrors 下增加国内的maven镜像源,下载依赖时提速明显。

<mirror>
  <id>CN</id>
  <name>Aliyun Nexus</name>
  <url>http://maven.aliyun.com/nexus/content/groups/public</url>
  <mirrorOf>central</mirrorOf>
</mirror>

4 创建项目

要使用maven,项目必须符合一定的目录规范,最简单的方法就是用maven来创建项目。

# mvn archetype:generate -DgroupId=example -DartifactId=howto -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
# tree howto
howto/
├── pom.xml
└── src
    ├── main
    │  └── java
    │       └── example
    │           └── App.java
    └── test
        └── java
            └── example
                └── AppTest.java

5 样板 pom.xml

除了目录结构外,pom.xml 是 maven 的核心, package 是包的类型 jar 或者 warproperties 中定义的值可以在其它地方引用, dependencies 定义依赖, build 定义构建过程需要的插件, reporting 定义构建完后的一些报告插件。maven的大部分功能都是通过插件提供的,后面会说一些比较有用的插件。

<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>example</groupId>
  <artifactId>howto</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>howto</name>
  <url>http://maven.apache.org</url>

  <properties>
    <java.version>1.8</java.version>
    <spring.version>4.2.5.RELEASE</spring.version>
    <jetty.http.port>8888</jetty.http.port>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>5.2.4.Final</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.9</version>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.3</version>
        <configuration>
          <compilerArgs>
            <arg>-Xlint:unchecked</arg>
            <arg>-Xlint:deprecation</arg>
          </compilerArgs>
          <source>${java.version}</source>
          <target>${java.version}</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.6</version>
        <configuration>
          <packagingExcludes>
            WEB-INF/lib/slf4j-api-*.jar
          </packagingExcludes>
          <failOnMissingWebXml>false</failOnMissingWebXml>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-maven-plugin</artifactId>
        <version>9.3.4.RC1</version>
        <configuration>
          <httpConnector>
            <port>${jetty.http.port}</port>
          </httpConnector>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <reporting>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-pmd-plugin</artifactId>
        <version>3.6</version>
      </plugin>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>findbugs-maven-plugin</artifactId>
        <version>3.0.3</version>
        <configuration>
          <excludeFilterFile>findbugs-exclude.xml</excludeFilterFile>
        </configuration>
      </plugin>
    </plugins>
  </reporting>
</project>

6 常用的maven命令和选项

  • mvn compile 编译
  • mvn test-compile 仅编译测试
  • mvn package 打 war 或者 jar
  • mvn clean 清除 package 或其它过程中产生的中间文件
  • mvn dependency:help 查看 dependency 插件的帮助
  • mvn site 查看项目报告,把 target/site 配置到 http doc 目录,可以以web方式查看
  • -T xC 使用x个cpu,例如:mvn test -T 1C,使用1个CPU运行mvn test

通过 MAVEN_OPTS 环境变量,可以设置java的启动参数,例如 export MAVEN_OPTS="-Xmx512M -Xms512M"

目标是可以组合的,例如 mvn clean package jetty:run

跳过某些插件的方法似乎是通用的:

  • 跳过测试插件 maven-test-plugin,-Dmaven.test.skip=true
  • 跳过 maven-antrun-plugin,-Dmaven.antrun.skip=true

7 mvn test 常用选项

  • -Dtest=my.package.TestCircle 只测试 TestCircle
  • -Dtest=my.package.TestCi*le 模糊匹配
  • -Dtest=my.package.TestSquare,my.package.TestCi*le 指定多个
  • -Dtest=my.package.TestCircle#mytest 指定方法
  • -Dtest=my.package.TestCircle#test* 模糊匹配
  • -Dtest=my.package.TestCircle#testOne+testTwo 指定多个方法

注意 这里TestCircle在my.package下,一定要带上包名。

8 管理依赖

通过 dependency 填写依赖,maven会在本地缓存一份数据 $HOME/.m2/repository 依赖管理是个很便捷的东西。c和c++就没有类似的项目,Makefile 里面指定的依赖额外安装。

8.1 处理maven仓库中不存在的库

有时候会碰到jar包不在标准maven仓库的情况,这时有两种选择,一种是自己搭建maven仓库,另一种是把jar把安装到maven缓存中,这里介绍第二种方法。

# download jar
curl http://path-to-jar/org.patchca.patchca-0.6.0.jar -o org.patchca.patchca-0.6.0.jar
# install jar to local mvn cache
mvn install:install-file -Dfile=org.patchca.patchca-0.6.0.jar -DgroupId=org.patchca -DartifactId=patchca -Dversion=0.6.0 -Dpackaging=jar

9 打出多种格式的包

假设应用除了提供web接口(这需要应用打包成war),还提供了一些小命令(这些小命令对war里面的class有依赖),此时除了war外,再打包出一个jar包供小命令用是个不错的选择。

通过build阶段的多个plugin,可以打出多种格式的包。

10 常用的maven插件

10.1 maven-compiler-plugin 插件

编译插件,配置编译选项

10.2 maven-war-plugin

打war包插件,配置打包选项

10.3 maven-jar-plugin

打jar包插件,不包含依赖

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <version>2.6</version>
  <executions>
    <execution>
      <id>make-a-jar</id>
      <phase>package</phase>
      <goals>
        <goal>jar</goal>
      </goals>
    </execution>
  </executions>
</plugin>

10.4 maven-dependency-plugin

提取所有的依赖

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <version>2.6</version>
  <executions>
    <execution>
      <id>copy</id>
      <phase>package</phase>
      <goals>
        <goal>copy-dependencies</goal>
      </goals>
      <configuration>
        <outputDirectory>${project.build.directory}/lib</outputDirectory>
      </configuration>
    </execution>
  </executions>
</plugin>

10.5 maven-assembly-plugin

打独立运行的jar包,build-plugins段

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
  <version>2.6</version>
  <configuration>
    <descriptorRefs>
      <descriptorRef>jar-with-dependencies</descriptorRef>
    </descriptorRefs>
  </configuration>
  <executions>
    <execution>
      <id>make-a-assembly</id>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
    </execution>
  </executions>
</plugin>

10.6 jetty-maven-plugin

jetty插件,通过 mvn jetty:run-war 运行war包,查看 5 虽然通过 jetty:run 也可以运行,但有时候会引起问题,尤其是关于 slf4j 的。例如:把依赖 slf4j-api 设置为 compile ,但是使用 jetty:run 却会加载 slf4j-api 。推荐使用 jetty:run-war 此时执行的是war包中的内容, slf4j-api 肯定不在里面,并且因为更接近真实环境,更能减少上线的bug。

通过jetty插件运行程序使用的是maven的日志配置,在 $MAVEN_HOME/conf/logging/simplelogger.properties 文件中,默认基本是 info,通过增加 org.slf4j.simpleLogger.log.example=debug 把example包(及子包)下的日志级别设置为debug,用于调试example包。如果 jetty:run 出现了 SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder" ,试试 jetty:run-war

10.7 maven-pmd-plugin

源码分析插件,发现隐藏的bug,参考 5

10.8 findbugs-maven-plugin

代码静态分析,发现隐藏的bug,参考 5

Author: zhengzhiyong

Created: 2023-10-22 日 12:01

Validate