Skip to content

Instantly share code, notes, and snippets.

@ericzhong
Last active November 26, 2017 15:00
Show Gist options
  • Save ericzhong/69e598f062437911f013d1e969fcccd5 to your computer and use it in GitHub Desktop.
Save ericzhong/69e598f062437911f013d1e969fcccd5 to your computer and use it in GitHub Desktop.
Maven 安装与使用

安装

Mac

brew install maven

Hello World

生成项目框架:

mvn -B archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes \
  -DgroupId=com.mycompany.app -DartifactId=my-app

目录结构如下:

$ tree my-app/
my-app/
|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |       `-- com
    |           `-- mycompany
    |               `-- app
    |                   `-- App.java
    `-- test
        `-- java
            `-- com
                `-- mycompany
                    `-- app
                        `-- AppTest.java

文件 src/main/java/com/mycompany/app/App.java 内容如下:

package com.mycompany.app;

public class App 
{
    public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
    }
}

文件 pom.xml 内容如下:

<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>my-app</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

打包后运行:

cd my-app
mvn package
java -cp target/my-app-1.0-SNAPSHOT.jar com.mycompany.app.App

或者,编译后运行:

cd my-app
mvn compile
java -cp target/classes com.mycompany.app.App

命令

mvn compile         # 输出在 target 目录中
mvn test            # 编译并运行测试代码
mvn test-compile    # 仅编译测试代码
mvn package         # 打包,可以是 jar,war,ear
mvn install         # 安装 target/*.jar 到本地仓库 ~/.m2/repository
mvn site            # 生成网站
mvn clean           # 删除 target 目录
mvn verify

操作

下载或更新依赖

运行如下命令会根据 pom.xml 更新依赖包到仓库:

mvn install -e -U        # -e 打印异常,-U 强制更新

打 JAR 包(含依赖)

需要插件 maven-assembly-plugin, 在 pom.xml 中增加:

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <mainClass>org.mycompany.app.my-app.App</mainClass>    <!-- 必须有 -->
            </manifest>
          </archive>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
        <!-- 去掉注释后可仅执行:mvn clean package,但会生成两个 JAR 包。
        <executions>  
          <execution>  
            <id>make-assembly</id>  
            <phase>package</phase>   
            <goals>  
              <goal>single</goal>  
            </goals>  
          </execution>  
        </executions>
        -->
      </plugin>
    </plugins>
  </build>

然后,打包:

mvn clean compile assembly:single -Dmaven.test.skip=true

运行:

java -jar *-jar-with-dependencies.jar

下载依赖的源码

mvn dependency:sources -DdownloadSources=true -DdownloadJavadocs=true

使用本地包

  • 方式一:

    <dependencies>  
      <dependency>  
        <groupId>*</groupId>  
        <artifactId>*</artifactId>  
        <version>*</version>
        <!-- 增加下面两行 -->
        <scope>system</scope>  
        <systemPath>${project.basedir}/lib/xxx.jar</systemPath>  
      </dependency>  
    </dependencies>  
  • 方式二:

    将他们安装到本地仓库中(包名要有版本号):

    mvn install:install-file -Dfile=xxx-1.0.jar -DgroupId=yyy -DartifactId=xxx -Dversion=1.0 -Dpackaging=jar

    然后 pom.xml 如下:

    <dependencies>  
      <dependency>  
        <groupId>yyy</groupId>  
        <artifactId>xxx</artifactId>  
        <version>1.0</version>  
      </dependency>
    </dependencies> 

打 JAR 包(不含依赖)

如果依赖包很多,最好将它们放在同一个目录下,因此需要用到如下插件:

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <mainClass>org.mycompany.app.learn_mahout.Recommender</mainClass>
              <addClasspath>true</addClasspath>
              <classpathPrefix>lib/</classpathPrefix>
            </manifest>
          </archive>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
          <execution>
            <id>copy-dependencies</id>
            <phase>package</phase>
            <goals>
              <goal>copy-dependencies</goal>
            </goals>
            <configuration>
              <!-- exclude junit, we need runtime dependency only -->
              <includeScope>runtime</includeScope>
              <outputDirectory>${project.build.directory}/lib/</outputDirectory>
              <overwriteifnewer>true</overwriteifnewer>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

然后,打包并运行:

mvn package
java -jar target/learn-mahout-0.0.1-SNAPSHOT.jar

如果依赖包在其它目录下,可以执行:

java -cp learn-mahout-0.0.1-SNAPSHOT.jar:../learn-mahout/target/lib/* org.mycompany.app.learn_mahout.Recommender

注意,-classpath 需要指定 JAR 包和依赖包所在目录(必须*号结尾),然后指定运行类,不能再用 -jar 选项。

如果依赖包不多也可以全部放到选项中(Unix 用:分隔,Windows 用;):

java -cp learn-mahout-0.0.1-SNAPSHOT.jar:/path/to/a.jar:/path/to/b.jar:/path/to/c.jar org.mycompany.app.learn_mahout.Recommender

概念

SNAPSHOT

表示开发分支的最新版本。

1.0-SNAPSHOT 发布后就应该变成 1.0,而最新的开发版本就变成 1.1-SNAPSHOT

-DskipTests 和 -Dmaven.test.skip=true

都是关于 JUnit 测试用例的选项。前者不测试但编译,后者既不测试也不编译。

Troubleshooting

no main manifest attribute in jar

如果是运行 mvn package 时报错,原因是缺少如下配置:

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <mainClass>org.mycompany.app.my-app.App</mainClass>
            </manifest>
          </archive>
        </configuration>
      </plugin>

java.lang.NoClassDefFoundError

如果是执行 java -jar xxx-0.0.1-SNAPSHOT.jar 时报错,先把依赖包全部复制到 lib/ 下,然后执行:

java -cp xxx-0.0.1-SNAPSHOT.jar:lib/* org.mycompany.app.my-app.App

或者在选项中把依赖包全部列出来:

java -cp xxx-0.0.1-SNAPSHOT.jar:/path/to/a.jar:/path/to/b.jar:/path/to/c.jar org.mycompany.app.my-app.App
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment