关于Maven打包

无启动类的工程打成jar包

有一个无启动类的工程,要打成jar包直接给别的工程使用。

该工程的 pom.xml 打包配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source> <!-- 源代码使用的JDK版本 -->
<target>1.8</target> <!-- 需要生成的目标class文件的编译版本 -->
<encoding>UTF-8</encoding><!-- 字符集编码 -->
<skip>true</skip><!-- 跳过测试 -->
</configuration>
</plugin>
</plugins>
</build>

只能用maven-compiler-plugin,它适用于所有 maven 项目,无论其是不是 SpringBoot 项目;不能用spring-boot-maven-plugin,因为后者要求该工程必须有main方法。

关于跳过测试的配置<skip>true</skip>:

maven 打包时一般会选择不执行测试类,省时间。加上<skip>true</skip>的区别在于,mvn package 执行到maven-surefire-plugin会不会执行测试类:

1
2
3
4
5
6
7
8
9
10
11
///// 加上skip
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ spring-boot-web-jar-test ---
[INFO] No tests to run.

///// 不加skip
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ spring-boot-web-jar-test ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
......这里是测试类执行时打印的日志

因为该工程无启动类,所以测试类执行时一定会报错:java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration,所以该工程若有测试类,则打包时必须跳过测试类才能打包成功。

有启动类的工程打成jar包

一般的 SpringBoot Web 项目都有启动类,把这个项目工程打成 jar 包放到服务器上运行。

该工程的 pom.xml 打包配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

这个工程打包插件只需要使用spring-boot-maven-plugin,该插件的配置中的<goal>repackage</goal>的含义是:将当前工程打成可执行的,即有main方法的jar包。这里其实可以不加这个标签,因为<goal>repackage</goal>是该插件的默认选项,这就是“无启动类的工程”不能使用该插件打包的原因。

使用了spring-boot-maven-plugin插件打包,不会跳过测试类,要跳过测试类,可以再加入以下两个插件其中一个:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<skipTests>true</skipTests><!-- 跳过测试 -->
</configuration>
</plugin>


<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<skip>true</skip><!-- 跳过测试 -->
</configuration>
</plugin>

关于 repackage:

使用普通的 mvn package 打包时生成的 jar 包中,只包含工程中的 java 文件编译后的 class 文件和 resources 下的配置文件,没有BOOT-INF目录;而 SpringBoot 插件 repackage 后的 jar 包中,将该工程的 maven 依赖包都加入了BOOT-INF/lib目录下,同时 class 文件和配置文件也放在了BOOT-INF目录下,并在META-INF/MANIFEST.MF文件中指定了:

1
2
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/

所以,只有用 SpringBoot 插件 repackage 打包后的 jar 才是可执行的 jar,这个插件帮助我们设置启动 main 方法,并将所有 maven 依赖都添加到了 jar 包中,使得它可以独立运行。

依赖本地jar包的工程打成可执行jar包

有一个工程,在 resources 目录下有个 lib 目录,在这个目录下添加了多个该工程依赖的 jar 包。在 maven 打包时,要将这些 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
30
31
32
33
<build>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources/lib</directory><!--lib路径-->
<targetPath>BOOT-INF/lib/</targetPath>
<includes>
<include>**/*.jar</include>
</includes>
</resource>
</resources>

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

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<skip>true</skip>
<compilerArguments>
<extdirs>${project.basedir}/src/main/resources/lib</extdirs>
</compilerArguments>
</configuration>
</plugin>
</plugins>
</build>

resource标签的作用:将该工程 resources/lib 目录下所有 .jar 文件复制到spring-boot-maven-plugin插件打包后生成的 jar 中的BOOT-INF/lib/目录下,使得 jar 在运行时可以使用到这些依赖。

但只有 resource 标签还不够,因为 maven 打包前先编译,编译时会报找不到这些 jar 中的类,所以还需要添加maven-compiler-plugin,并指定其参数extdirs,使得 maven 编译时可以找到这些依赖,编译不会出错。

resource 标签:https://blog.csdn.net/qq_44651775/article/details/106545959

还有另一种方式也可以实现这个效果:

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
<!--本地依赖添加到 dependencies 中 -->
<dependency>
<groupId>com.example</groupId>
<artifactId>spring-boot-web-jar-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/spring-boot-web-jar-test-0.0.1-SNAPSHOT.jar</systemPath>
</dependency>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<!-- 将 scope=system 的依赖也添加到 BOOT-INF/lib 目录下 -->
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<skip>true</skip>
<compilerArguments>
<extdirs>${project.basedir}/src/main/resources/lib</extdirs>
</compilerArguments>
</configuration>
</plugin>
</plugins>
</build>