maven常用插件

综述

maven使用描述性语言来表达程序编译打包过程,make、ant使用过程性语言来表达程序编译打包过程,maven把过程都封装到了插件里面,这就使得maven很清晰。
maven构建过程中包括三种事物:生命周期、阶段、目标,这三种事物是过程抽象成的三种粒度。
maven内置三种生命周期:clean,default,site(很少用到)。mvn clean命令可以直接执行clean生命周期,但是不能使用mvn default来执行default生命周期。default生命周期是最重要、最复杂的生命周期,它由若干阶段(phase)组成,可以使用命令mvn DefaultPhase来执行default生命周期中的各个阶段。构建目标是Maven构建过程中最细化的步骤,一个目标可以与一个或多个构建阶段绑定,也可以不绑定。如果一个目标没有与任何构建阶段绑定,你只能将该目标的名称作为参数传递给mvn命令来执行它。如果一个目标绑定到多个构建阶段,该目标在绑定的构建阶段执行的同时被执行。

  • 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:将编译后的代码以可分配的形式打包,如Jar包。
  • pre-integration-test
  • integration-test
  • post-integration-test
  • verify
  • install:将项目打包后安装到本地仓库,可以作为其它项目的本地依赖。
  • deploy:将最终的包复制到远程仓库,与其它开发者和项目共享。

maven的default生命周期各个phase绑定的插件:

phase 插件:goal
generate-resources plugin:descriptor
process-resources resources:resources
compile compiler:compile
process-test-resources resources:testResources
test-compile compiler:testCompile
test surefire:test
package jar:jar and plugin:addPluginArtifactMetadata
install install:install
deploy deploy:deploy

可以通过命令查看插件的详细信息:

mvn help:describe -Dplugin=org.apache.maven.plugins:maven-compile-plugin –Ddetail

官方文档:Maven生命周期
官方文档:Maven核心插件

编译插件maven-compiler

maven的编译插件可以用来设置源码的JDK版本、目标平台JDK版本、源码编码。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.2</version>
    <configuration>
           <source>1.8</source>
           <target>1.8</target>
           <encoding>utf-8</encoding>
    </configuration>
</plugin>

指定Java版本的另一种方式:通过属性指明版本。

<profile>
    <id>jdk1.7</id>
    <activation>
        <activeByDefault>true</activeByDefault>
        <jdk>1.7</jdk>
    </activation>
    <properties>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
        <maven.compiler.compilerVersion>1.7</maven.compiler.compilerVersion>
    </properties>
</profile>

也可以不必指明profile,直接指明properties

<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

compiler-plugin可以指定编译时参数

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.6.0</version>
    <configuration>
        <source>1.8</source> <!-- 源代码使用jdk1.8支持的特性 -->
        <target>1.8</target> <!-- 使用jvm1.8编译目标代码 -->
            <compilerArgs> <!-- 传递参数 -->
                <arg>-parameters</arg>
                <arg>-Xlint:unchecked</arg>
                <arg>-Xlint:deprecation </arg>
            </compilerArgs>
    </configuration>
</plugin>

maven-shade

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.1</version>
        <configuration>
          <!-- put your configurations here -->
        </configuration>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <minimizeJar>true</minimizeJar>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

maven-assembly

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <mainClass>cnblog.Cmd</mainClass>
            </manifest>
            <manifestEntries>
                <Class-Path>.</Class-Path>
            </manifestEntries>
        </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>

打包插件maven-jar

maven-jar插件可以将源码打成包含依赖的jar包,不过maven-jar如果包含依赖需要使用maven-dependency插件,两个插件配合才能将依赖+源码打成一个jar包。

<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>MavenJarExtractor</mainClass>
            </manifest>
        </archive>
        <finalName>mavenjar</finalName>
    </configuration>
</plugin>

依赖打包插件maven-dependency

maven-dependency的作用是把依赖打包到lib里面去。

<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>

并行运行测试的插件:maven-surefire

maven-surefire插件用于指定测试用例的一些规则。这个插件是maven自带的插件,可以不必在pom.xml中指明。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <skipAfterFailureCount>1</skipAfterFailureCount>  <!-- 只要有一个用例测试失败,就立即停止。默认情况下会跑完所有测试用例 -->
        <rerunFailingTestsCount>2</rerunFailingTestsCount>  <!-- 失败重试次数 -->
        <parallel>methods</parallel>  <!-- 并发执行测试用例 -->
        <threadCount>10</threadCount>  <!-- 并发执行时的线程数量 -->
    </configuration>
</plugin>

常用命令

// 跳过测试用例
mvn test -Dmaven.test.skip=true
// 或
mvn test -DskipTests=true

// 运行指定的测试用例
mvn test -Dtest=*2Test
mvn test -Dtest=App2Test,AppTest
mvn test -Dtest=???2Test
mvn test -Dtest=*Test#testAdd

springboot-maven-plugin

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>

如果指定了spring-boot作为parent,可以不指定版本和repackage goal:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.3.8.RELEASE</version>
    <configuration>
        <mainClass>${start-class}</mainClass>
   </configuration>
</parent>

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

spring-boot查找main文件的流程是:

  • 首先查看是否有值,如果有,直接拿标签内的类名作为入口。
com.example.Application ``` * 如果没找到``标签,会遍历所有文件,找到注解了`@SpringBootApplication`并含有main方法的类,将其作为入口。 实践证明,如果没有定义``,查找入口类的方法也是非常快的。 在实际开发中,推荐手动定义``。这样在一个项目工程中可以有多个`@SpringBootApplication`注解的类,修改一下pom里的配置就能灵活切换入口了。

maven打包并通过windows脚本运行

创建一个文件夹haha,里面包含三项

  • Haha.java
  • Main.java
  • pom.xml

pom.xml

<?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.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>wyf</groupId>
    <artifactId>CloneSite</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <sourceDirectory>.</sourceDirectory>
        <finalName>haha</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <encoding>utf-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

maven遵守约定大于配置的原则,它有一套默认的目录结构,但是也可以在build中指定源代码目录和资源文件目录。

Main.java

public class Main{
    public static void main(String[] args) {
        System.out.println("天下大势为我所控");
    }
}

Haha.java

public class Haha {
    public static void main(String[] args) {
        System.out.println("hello world");
    }
}

在此文件夹下打开cmd,mvn package,打包即可生成target目录。
cd到target,执行java -cp haha.jar Main就会运行Main类,执行java -cp haha.jar Haha就会运行Haha类。
我认为这种运行jar包的方式相对于直接打包成可运行的jar包更好,因为这样打包更简单。
可执行jar包其实也可以使用java -cp haha.jar Something的方式运行其它类,只不过它有默认的主类。

有时会遇到“错误: 找不到或无法加载主类”这样的错误,一个很可能的原因是类加载异常。比如class Haha继承了某个类A,而这个类A却又在classpath中找不到,那么就会报错:Haha找不到或者无法加载。实际上是无法加载。

要想使所有的依赖都能够找到,需要maven打包时导出所有依赖包:

<build>
    <finalName>clonesite</finalName>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>utf-8</encoding>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <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>
    </plugins>
</build>

而运行的时候,java -cp lib/one.jar;lib/two.jar;mine.jar MyClass,lib中的所有jar包都要出现在cp参数中,无法使用文件夹+通配符的方式。

原文地址:https://www.cnblogs.com/weiyinfu/p/8364862.html