加载中...
Featured image of post 5 build标签和插件

5 build标签和插件

maven的使用,build标签和插件

一、插件和目标

1、插件

Maven 的核心程序仅仅负责宏观调度,不做具体工作。具体工作都是由 Maven 插件完成的。例如:编译就是由 maven-compiler-plugin-3.1.jar 插件来执行的。

2、目标

一个插件可以对应多个目标,而每一个目标都和生命周期中的某一个环节对应。

Default 生命周期中有 compile 和 test-compile 两个和编译相关的环节,这两个环节对应 compile 和 test-compile 两个目标,而这两个目标都是由 maven-compiler-plugin-3.1.jar 插件来执行的。

3、调用插件的方法

方式一:通过生命周期映射的方式,将插件的goal绑定到生命周期中的phase上,然后调用phase。例如:maven-jar-plugin插件提供了一个叫jar的goal,默认会绑定到生命周期的package阶段(phase)。调用mvn package就会自动调用maven-jar-plugin:jar生命周期中所有前置的phase会先自动执行。

1
package <==> maven-jar-plugin:jar
Copied!

方式二:直接调用插件的某个功能(goal)。如mvn maven-jar-plugin:jar。maven有一个约定,如果插件的名字叫maven-xxxx-plugin或xxxx-maven-plugin的话。可以直接用mvn xxxx:goal的方式调用其提供的功能。所以前面这个命令就可以简写成:mvn jar:jar这种方式只会执行指定的goal

调用goal完整的命令格式为:

1
2
  mvn <plugin-prefix>:<goal>
  mvn [<plugin-group-id>:]<plugin-artifact-id>[:<plugin-version>]:<goal>
Copied!

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

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

二、build标签

1、介绍

在实际使用 Maven 的过程中,我们会发现 build 标签有时候有,有时候没,这是怎么回事呢?其实通过有效 POM 我们能够看到,build 标签的相关配置其实一直都在,只是在我们需要定制构建过程的时候才会通过配置 build 标签覆盖默认值或补充配置。这一点我们可以通过打印有效 POM 来看到。

所以本质上来说:我们配置的 build 标签都是对超级 POM 配置叠加。那我们又为什么要在默认配置的基础上叠加呢?很简单,在默认配置无法满足需求的时候定制构建过程

2、build标签组成

①、定义约定的目录结构

参考示例中的如下部分:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<sourceDirectory>D:\idea2019workspace\atguigu-maven-test-prepare\src\main\java</sourceDirectory>
<scriptSourceDirectory>D:\idea2019workspace\atguigu-maven-test-prepare\src\main\scripts</scriptSourceDirectory>
<testSourceDirectory>D:\idea2019workspace\atguigu-maven-test-prepare\src\test\java</testSourceDirectory>
<outputDirectory>D:\idea2019workspace\atguigu-maven-test-prepare\target\classes</outputDirectory>
<testOutputDirectory>D:\idea2019workspace\atguigu-maven-test-prepare\target\test-classes</testOutputDirectory>
<resources>
    <resource>
        <directory>D:\idea2019workspace\atguigu-maven-test-prepare\src\main\resources</directory>
    </resource>
</resources>
<testResources>
    <testResource>
        <directory>D:\idea2019workspace\atguigu-maven-test-prepare\src\test\resources</directory>
    </testResource>
</testResources>
<directory>D:\idea2019workspace\atguigu-maven-test-prepare\target</directory>
Copied!

我们能看到各个目录的作用如下:

目录名作用
sourceDirectory主体源程序存放目录
scriptSourceDirectory脚本源程序存放目录
testSourceDirectory测试源程序存放目录
outputDirectory主体源程序编译结果输出目录
testOutputDirectory测试源程序编译结果输出目录
resources主体资源文件存放目录
testResources测试资源文件存放目录
directory构建结果输出目录

②、备用插件管理

pluginManagement 标签存放着几个极少用到的插件:

  • maven-antrun-plugin
  • maven-assembly-plugin
  • maven-dependency-plugin
  • maven-release-plugin

通过 pluginManagement 标签管理起来的插件就像 dependencyManagement 一样,子工程使用时可以省略版本号,起到在父工程中统一管理版本的效果。情看下面例子:

  • 被 spring-boot-dependencies 管理的插件信息:
1
2
3
4
5
6
7
8
9
<pluginManagement>
      <plugins>
          <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>2.6.2</version>
          </plugin>
  		</plugins>
</pluginManagement>
Copied!
  • 子工程使用的插件信息:
1
2
3
4
5
6
7
8
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
Copied!

③、插件结构

plugins 标签存放的是默认生命周期中实际会用到的插件,这些插件想必大家都不陌生,所以抛开插件本身不谈,我们来看看 plugin 标签的结构:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <executions>
        <execution>
            <id>default-compile</id>
            <phase>compile</phase>
            <goals>
                <goal>compile</goal>
            </goals>
        </execution>
        <execution>
            <id>default-testCompile</id>
            <phase>test-compile</phase>
            <goals>
                <goal>testCompile</goal>
            </goals>
        </execution>
    </executions>
</plugin>
Copied!

[1] 坐标部分

  • artifactId 和 version 标签定义了插件的坐标,作为 Maven 的自带插件这里省略了 groupId。

[2] 执行部分

executions 标签内可以配置多个 execution 标签,execution 标签内:

  • id:指定唯一标识
  • phase:关联的生命周期阶段
  • goals/goal:关联指定生命周期的目标
    • goals 标签中可以配置多个 goal 标签,表示一个生命周期环节可以对应当前插件的多个目标。
  • 另外,插件目标的执行过程可以进行配置,例如 maven-site-plugin 插件的 site 目标:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<execution>
    <id>default-site</id>
    <phase>site</phase>
    <goals>
        <goal>site</goal>
    </goals>
    <configuration>
        <outputDirectory>D:\idea2019workspace\atguigu-maven-test-prepare\target\site</outputDirectory>
        <reportPlugins>
            <reportPlugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-project-info-reports-plugin</artifactId>
            </reportPlugin>
        </reportPlugins>
    </configuration>
</execution>
Copied!
  • configuration 标签内进行配置时使用的标签是插件本身定义的。就以 maven-site-plugin 插件为例,它的核心类是 org.apache.maven.plugins.site.render.SiteMojo,在这个类中我们看到了 outputDirectory 属性:

  • SiteMojo 的父类是:AbstractSiteRenderingMojo,在父类中我们看到 reportPlugins 属性:

  • 结论:每个插件能够做哪些设置都是各个插件自己规定的,无法一概而论。

三、定义jdk版本和编码

1、直接使用默认取值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<properties>
      	<!-- maven-resources-plugin和maven-compiler-plugin插件的默认取值 -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  
  			<!-- maven-site-plugin等插件的默认取值 -->
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      
      	<!-- maven-compiler-plugin插件的默认取值 -->
      	<maven.compiler.source>1.8</maven.compiler.source>
    		<maven.compiler.target>1.8</maven.compiler.target>
      
      	<!-- spring-boot-starter-parent里定义的的默认取值 -->
        <java.version>1.8</java.version>
      
</properties>
Copied!

2、或者在插件中定义

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<project>
  [...]
  <!-- build 标签:意思是告诉 Maven,你的构建行为,我要开始定制了! -->
  <build>
    [...]
    <!-- plugins 标签:Maven 你给我听好了,你给我构建的时候要用到这些插件! -->
    <plugins>
      
      <!-- JDK版本 -->
      <plugin>
        <!-- 插件的坐标。此处引用的 maven-compiler-plugin 插件不是第三方的,是一个 Maven 自带的插件。 -->
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.10.1</version>
        <!-- configuration 标签:配置 maven-compiler-plugin 插件 -->
        <configuration>
          <!-- 具体配置信息会因为插件不同、需求不同而有所差异 -->
          <source>1.8</source>
          <target>1.8</target>
          <encoding>UTF-8</encoding>
        </configuration>
      </plugin>
    
    	<!-- 编码 -->
   		<plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <version>3.2.0</version>
        <configuration>
          ...
          <encoding>UTF-8</encoding>
          ...
        </configuration>
      </plugin>
      
      
      
    </plugins>
    [...]
  </build>
  [...]
</project>
Copied!

source 标签含义

翻译过来就是:调用 Java 编译器命令时传入的 -source 参数。那对编译器来说,-source 参数是啥意思呢?

『提供与指定发行版的源兼容性』这句话我的理解是:

  • 我们写代码是按 JDK 1.8 写的——这就是『源兼容性』里的『源』。
  • 指定发行版就是我们指定的 JDK 1.8。
  • 『兼容性』是谁和谁兼容呢?现在源代码是既定的,所以就是要求编译器使用指定的 JDK 版本来兼容我们的源代码。

target 标签含义

调用 Java 编译器命令时传入的 -target 参数

『生成特定 VM 版本的类文件』这句话我的理解是:

  • VM 指 JVM
  • 类文件指 *.class 字节码文件
  • 整体意思就是源文件编译后,生成的 *.class 字节码文件要符合指定的 JVM 版本

3、或写在超级pom里,全局设定

配置的方式是:将 profile 标签整个复制到 settings.xml 文件的 profiles 标签内。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<profile>
	  <id>jdk-1.8</id>
	  <activation>
		<activeByDefault>true</activeByDefault>
		<jdk>1.8</jdk>
	  </activation>
	  <properties>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
		<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
	  </properties>
</profile>
Copied!

不推荐,仅在本地生效,如果脱离当前的settings.xml能够覆盖的范围,则无法生效

四、help 插件的各个目标

官网说明地址:https://maven.apache.org/plugins/maven-help-plugin

目标说明
help:active-profiles列出当前已激活的 profile
help:all-profiles列出当前工程所有可用 profile
help:describe描述一个插件和/或 Mojo 的属性
help:effective-pom以 XML 格式展示有效 POM
help:effective-settings为当前工程以 XML 格式展示计算得到的 settings 配置
help:evaluate计算用户在交互模式下给出的 Maven 表达式
help:system显示平台详细信息列表,如系统属性和环境变量

五、springboot打包插件

1、打包

1
2
3
4
5
6
7
8
9
<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
			<version>2.5.5</version>
		</plugin>
	</plugins>
</build>
Copied!

很显然 spring-boot-maven-plugin 并不是 Maven 自带的插件,而是 SpringBoot 提供的,用来改变 Maven 默认的构建行为。具体来说是改变打包的行为。默认情况下 Maven 调用 maven-jar-plugin 插件的 jar 目标,生成普通的 jar 包。

普通 jar 包没法使用 java -jar xxx.jar 这样的命令来启动、运行,但是 SpringBoot 的设计理念就是每一个『微服务』导出为一个 jar 包,这个 jar 包可以使用 java -jar xxx.jar 这样的命令直接启动运行。

这样一来,打包的方式肯定要进行调整。所以 SpringBoot 提供了 spring-boot-maven-plugin 这个插件来定制打包行为。

2、插件的七个目标

目标名称作用
spring-boot:build-imagePackage an application into a OCI image using a buildpack.
spring-boot:build-infoGenerate a build-info.properties file based on the content of the current MavenProject.
spring-boot:helpDisplay help information on spring-boot-maven-plugin. Call mvn spring-boot:help -Ddetail=true -Dgoal= to display parameter details.
spring-boot:repackageRepackage existing JAR and WAR archives so that they can be executed from the command line using java -jar. With layout=NONE can also be used simply to package a JAR with nested dependencies (and no main class, so not executable).
spring-boot:runRun an application in place.
spring-boot:startStart a spring application. Contrary to the run goal, this does not block and allows other goals to operate on the application. This goal is typically used in integration test scenario where the application is started before a test suite and stopped after.
spring-boot:stopStop an application that has been started by the ‘start’ goal. Typically invoked once a test suite has completed.

六、自定义插件

1、创建工程

  • 创建一个常规的maven工程

  • 然后修改打包方式:

    1
    
    <packaging>maven-plugin</packaging>
    Copied!
  • 引入依赖(二选一):

    [1] 将来在文档注释中使用注解

    1
    2
    3
    4
    5
    
    <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-plugin-api</artifactId>
        <version>3.5.2</version>
    </dependency>
    Copied!

    [2] 将来直接使用注解

    1
    2
    3
    4
    5
    
    <dependency>
        <groupId>org.apache.maven.plugin-tools</groupId>
        <artifactId>maven-plugin-annotations</artifactId>
        <version>3.5.2</version>
    </dependency>
    Copied!
  • 创建 Mojo 类

    Mojo 类是一个 Maven 插件的核心类。

    Mojo 这个单词的意思是:Maven Old Java Object,其实 mojo 这个单词本身包含魔力;符咒(袋);护身符;(人的)魅力的含义,Maven 用 Mojo 是因为它是对 POJO 开的一个小玩笑。

    [1] Mojo 接口

    每一个 Mojo 都需要实现 org.apache.maven.plugin.Mojo 接口

**[2] AbstractMojo 抽象

我们实现 Mojo 接口比较困难,幸好可以继承 AbstractMojo,此时我们只要实现 execute() 这一个方法即可。

1
2
3
4
5
6
public class MyHelloPlugin extends AbstractMojo {
    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        getLog().info("---> This is my first maven plugin. <---");
    }
}
Copied!

2、插件配置

①、Mojo 类中的配置

  • [1]文档注释中用注解

​ 对应的 pom.xml 中的依赖: maven-plugin-api

images

  • [2]直接在类上标记注解

​ 对应 pom.xml 中的依赖:maven-plugin-annotations

1
2
3
4
5
6
7
8
// name 属性:指定目标名称
@Mojo(name = "firstBlood")
public class MyPluginOfFistBlood extends AbstractMojo {
    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        getLog().info("---> first blood <---");
    }
}
Copied!

②、安装插件

要在后续使用插件,就必须至少将插件安装到本地仓库。 mvn install

③、注册插件

我们需要将插件坐标中的 groupId 部分注册到 settings.xml 中。

1
2
3
4
5
6
7
<pluginGroups>
	<!-- pluginGroup
	 | Specifies a further group identifier to use for plugin lookup.
	<pluginGroup>com.your.plugins</pluginGroup>
	-->
	<pluginGroup>com.atguigu.maven</pluginGroup>
</pluginGroups>
Copied!

3、使用插件

①、识别插件前缀

Maven 根据插件的 artifactId 来识别插件前缀。例如下面两种情况:

[1]前置匹配

  • 匹配规则:${prefix}-maven-plugin
  • artifactId:hello-maven-plugin
  • 前缀:hello

[2]中间匹配

  • 匹配规则:maven-${prefix}-plugin
  • artifactId:maven-good-plugin
  • 前缀:good

②在命令行直接用

  • 命令:
1
mvn hello:sayHello
Copied!
  • 效果:

    images

③、配置到 build 标签里用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<build>
	<plugins>
		<plugin>
			<groupId>com.atguigu.maven</groupId>
			<artifactId>hello-maven-plugin</artifactId>
			<version>1.0-SNAPSHOT</version>
			<executions>
				<execution>
                    <id>hello</id>
                    <!-- 指定和目标关联的生命周期阶段 -->
					<phase>clean</phase>
					<goals>
						<goal>sayHello</goal>
					</goals>
				</execution>
                <execution>
                    <id>blood</id>
                    <phase>validate</phase>
                    <goals>
                        <goal>firstBlood</goal>
                    </goals>
                </execution>
			</executions>
		</plugin>
	</plugins>
</build>
Copied!

执行已和插件目标绑定的生命周期:

images

七、maven常用插件

1、maven-compiler-plugin

默认绑定到comile phase。用于编译项目源代码。 compile目标会编译src/main/java目录下的源代码。 testCompile目标会编译src/test/java目录下的测试代码。

maven compile编译源代码。 maven testCompile编译源代码+测试代码。

配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<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编译目标代码 -->
      	<encoding>utf-8</encoding> <!-- 编码 -->
      	<skipTests>true</skipTests>  <!-- 是否跳过测试 -->
  			<showWarnings>true</showWarnings>
      	<meminitial>128m</meminitial> <!-- 编译器使用的初始内存 -->
      	<maxmem>512m</maxmem>  <!-- 编译器使用的最大内存 -->
      	<compilerArgs> <!-- 传递参数 --> 
          <compilerArgs> <!-- 传递参数 -->
                        <arg>-Xlint:unchecked</arg><!--启用对未经检查的转换的警告   Map map = new HashMap();
                                                         map.put("a", new A());-->
                        <arg>-Xlint:deprecation</arg><!--显示关于使用了过时的 API 的详细信息-->
        </compilerArgs>
    </configuration>
</plugin>
Copied!

用户可以通过两种方式调用Maven插件目标。

第一种方式是将插件目标与生命周期阶段(lifecycle phase)绑定,这样用户在命令行只是输入生命周期阶段而已,例如Maven默认将maven-compiler-plugin的compile目标与compile生命周期阶段绑定,因此命令mvn compile实际上是先定位到compile这一生命周期阶段,然后再根据绑定关系调用maven-compiler-plugin的compile目标。

第二种方式是直接在命令行指定要执行的插件目标,例如mvn archetype:generate 就表示调用maven-archetype-plugin的generate目标,这种带冒号的调用方式与生命周期无关。

2、maven-resources-plugin

①、分环境配置

  • 配置目录
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <version>2.5</version>
    <configuration>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <!-- 先把所有环境的配置全部排除 -->
                <excludes>
                    <exclude>dev/**</exclude>
                    <exclude>prod/**</exclude>
                </excludes>
            </resource>
            <resource>
                <directory>src/main/resources/${active.profile}</directory>
                <!-- 再把当前环境的配置引入 -->
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
            </resource>
        </resources>
    </configuration>
</plugin>
<!-- 或者 -->
<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <!-- 先把所有环境的配置全部排除 -->
            <excludes>
                <exclude>dev/**</exclude>
                <exclude>prod/**</exclude>
            </excludes>
        </resource>
        <resource>
            <directory>src/main/resources/${active.profile}</directory>
            <!-- 再把当前环境的配置引入 -->
            <includes>
                <include>**/*.xml</include>
                <include>**/*.properties</include>
            </includes>
        </resource>
    </resources>
</build>
Copied!
  • 配置profile
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<profiles>
    <profile>
        <id>dev</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <active.profile>dev</active.profile>
        </properties>
    </profile>
    <profile>
        <id>prod</id>
        <properties>
            <active.profile>prod</active.profile>
        </properties>
    </profile>
</profiles>
Copied!

②、打源码包

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <version>3.0.1</version>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>jar-no-fork</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
</build>
Copied!

3、maven-surefire-plugin

用于跑测试用例

此插件可以不在pom.xml里面声明,maven运行命令时,会自动调用该插件。 一些有用的配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
      	<testFailureIgnore>true</testFailureIgnore>  <!--测试有失败用例时,是否继续构建-->
      	<skipTests>true</skipTests>                  <!--是否跳过测试阶段,方式1-->
      <skip>true</skip>                            <!--是否跳过测试阶段,方式2-->
        <skipAfterFailureCount>1</skipAfterFailureCount>  <!-- 只要有一个用例测试失败,就立即停止。默认情况下会跑完所有测试用例 -->
        <rerunFailingTestsCount>2</rerunFailingTestsCount>  <!-- 失败重试次数 -->
        <parallel>methods</parallel>  <!-- 并发执行测试用例 -->
        <threadCount>10</threadCount>  <!-- 并发执行时的线程数量 -->
    </configuration>
</plugin>
Copied!

4、spring-boot-maven-plugin

spring-boot开发必备插件。它能将spring-boot项目代码及其依赖jar打包成一个完整的可执行的jar包(fat jar)作用和插件maven-shade-plugin差不多。 repackage的goal绑定在生命周期的package阶段。 使用方式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>
Copied!

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<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>
Copied!

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

1、首先查看<mainClass>是否有值,如果有,直接拿标签内的类名作为入口。

1
2
3
<properties>
    <start-class>com.example.Application</start-class>
</properties>
Copied!

2、如果没找到<start-class>标签,会遍历所有文件,找到注解了@SpringBootApplication并含有main方法的类,将其作为入口。 实践证明,如果没有定义<start-class>,查找入口类的方法也是非常快的。 在实际开发中,推荐手动定义<start-class>。这样在一个项目工程中可以有多个@SpringBootApplication注解的类,修改一下pom里的配置就能灵活切换入口了。

5、maven-jar-plugin

这个是普通java项目(非java web项目和其他特殊类型的java项目)package阶段默认绑定的插件,能够将编译好的class和资源打成jar包。

  • 常用配置:打出可以运行的有主类的jar包
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<plugin>  
    <groupId>org.apache.maven.plugins</groupId>  
    <artifactId>maven-jar-plugin</artifactId>
    <version>3.0.2</version>
    <configuration>  
        <archive>  
          	<!--加描述-->
            <addMavenDescriptor>false</addMavenDescriptor>  
            <manifest>  
              	<!--是否要把第三方jar放到manifest的classpath中-->
                <addClasspath>true</addClasspath>  
              	<!--生成的manifest中classpath的前缀,因为要把第三方jar放到lib目录下,不是代码里的目录-->
                <classpathPrefix>lib/</classpathPrefix>  
              <!-- 执行的主程序路径 -->
                <mainClass>com.meix.boot.Application</mainClass>  
            </manifest>
        </archive>  
         <!-- 过滤掉不希望包含在jar中的文件  -->  
        <excludes>  
            <exclude>*.xml</exclude>  
            <exclude>spring/**</exclude>  
            <exclude>config/**</exclude>  
        </excludes> 
        <!-- 把配置的这个目录下的部分资源打包,其他目录的java类不打 -->
        <includes>
            <include>**/api/*</include>
        </includes>         
    </configuration>  
</plugin>
Copied!
  • 把maven依赖的jar复制到lib目录下
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<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>
Copied!

打开 MENIFEST.MF 文件可以看到如下内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: sandy
//表示依赖的第三方jar包在哪里,显然需要放在和 当前jar包同级目录下的 lib文件夹下
Class-Path: lib/gson-2.8.5.jar lib/guava-19.0.jar lib/slf4j-api-1.7.25
 .jar lib/logback-core-1.2.3.jar lib/logback-access-1.2.3.jar lib/logb
 ack-classic-1.2.3.jar lib/lombok-1.18.2.jar lib/commons-lang3-3.8.1.j
 ar lib/commons-io-2.2.jar     
Created-By: Apache Maven 3.5.2
Build-Jdk: 1.8.0_121
Main-Class: com.example.demo.test.App  //表示运行的主程序
Copied!

所以安装包的路径结构应该是:

img

为此需要 通过 maven-assembly-plugin 插件来组装出安装包。

针对本示例 对应的 maven-assembly-plugin 配置如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-assembly-plugin</artifactId>
      <executions>
        <execution>
          <id>make-assembly</id>
          <phase>package</phase>
          <goals>
            <goal>single</goal>
          </goals>
        </execution>
      </executions>
      <configuration>
        <descriptors>  
          <!-- 和 pom.xml 同级目录下 -->
          <descriptor>assembly.xml</descriptor>
        </descriptors>
        <!-- assembly 组装出来的包会被放置在和 pom.xml同级目录下的output目录下 -->
        <outputDirectory>output</outputDirectory>
        <!-- true:会在生成的zip包名后面加上 id-->
        <appendAssemblyId>false</appendAssemblyId>
      </configuration>
</plugin>
Copied!

assembly.xml 内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?xml version='1.0' encoding='UTF-8'?>
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
    <id>test-maven</id>
    <formats>
        <format>zip</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <fileSets>
        <fileSet>
            <!-- ${project.build.directory} 指 target目录 -->
            <directory>${project.build.directory}</directory>
            <!-- 表示输出到 pom 中配置的 output目录下 -->
            <outputDirectory>/</outputDirectory>
            <includes>
                <!-- 把jar放入zip包根目录 -->
                <include>test-maven*.jar</include>
                <!-- dependency插件复制的依赖jar放入zip -->
                <include>lib/*</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>${project.build.directory}/classes</directory>
            <!-- 表示输出到 pom 中配置的 output/config 目录下 -->
            <outputDirectory>/config</outputDirectory>
            <includes>
                <include>application.properties</include>
            </includes>
        </fileSet>
        <fileSet>
            <!-- ${project.basedir} 指 工程根目录 -->
            <directory>${project.basedir}</directory>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>doc/*.*</include>
            </includes>
        </fileSet>
    </fileSets>
</assembly>
Copied!

要自定义 jar 包名称,可以直接在 pom.xml 中 build 结点下设置 finalName,如:

1
2
3
<build>
      <finalName>p-test-tool</finalName>
</build>
Copied!

6、maven-assembly-plugin

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <descriptorRefs>
                        <!-- 使用官方的打包策略 -->
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>a.App</mainClass>
                        </manifest>
                    </archive>
                    <!-- assembly 组装出来的包会被放置在和 pom.xml同级目录下的output目录下 -->
                    <outputDirectory>output</outputDirectory>
                    <!-- true:会在生成的zip包名后面加上 id-->
                    <appendAssemblyId>false</appendAssemblyId>
                </configuration>
            </plugin>
        </plugins>
    </build>
Copied!

7、maven-shade-plugin

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.3.0</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                  <mainClass>org.sonatype.haven.HavenCli</mainClass>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
Copied!
Licensed under CC BY-NC-SA 4.0
最后更新于 2024年5月10日 01:57
发表了90篇文章 · 总计613.28k字
本站总访问量本站访客数人次

目录