目录
零:说在前面
一:常用插件的介绍
二:常用插件的对比
三:打一个瘦jar包
3.1:背景
3.2:解决方案
四:插件应用举例
4.1:maven-jar-plugin 举例及部分说明
4.2:maven-dependency-plugin 举例及部分说明
4.3:maven-resources-plugin 举例及部分说明
五:附录
零:说在前面
Maven插件很多,但是本人感觉真正常用的有这么几个:spring-boot-maven-plugin、maven-jar-plugin、maven-resource-plugin、maven-dependency-plugin、maven-assembly-plugin。下面分别介绍并举例
一:常用插件的介绍
1.1:spring-boot-maven-plugin
负责将源码和依赖、以及springboot loader相关内容打成一个包。保证打出的包能独立运行。
1.2:maven-jar-plugin
仅负责将源码打成jar包,不能独立运行。另外,可以根据你的设置,将依赖jar包路径和程序的主入口定义在所打jar包中的 MANIFEST.MF 文件里。
1.3:maven-dependency-plugin
负责将各种依赖打包。也可以根据你的设置,将所打的依赖jar包输出到指定位置。
1.4:maven-resource-plugin
负责将正式与测试用到的资源文件导出到指定位置。还负责用资源文件中的参数替换pom文件中对应的占位符。
1.5:maven-assembly-plugin
负责打包。但是至少要指定需要打哪些内容,这个插件才能正常干活儿。
1.6:maven-surefire-plugin
负责测试。这一插件可以在maven的test阶段单独执行,在编译打包阶段可以被执行或跳过。可以指定其测试的范围或全量执行所有以Test开头或结尾的代码。
二:常用插件的对比
2.1:spring-boot-maven-plugin 相当于 jar-plugin 和 dependency-plugin 的功能合成。与那两个插件相比,spring-boot-maven-plugin 会把springboot的一些个性化的内容打到包里。比如上面提到的 springboot loader 内容。
2.2:maven-assembly-plugin 是基于 jar-plugin 和 dependency-plugin 的成果做了二次加工。它会把其他插件打出的jar包以及用户指定的额外项目也打入到成品之中。换言之,如果你用spring-boot-maven-plugin 搭配 maven-assembly-plugin 一起工作 和 maven-jar-plugin 搭配 maven-assembly-plugin 一起工作得到的产物会有不同。
三:打一个瘦jar包
3.1:背景
在Dev/Ops开发运维一体化思想大行其道的今天,技术部门对CI/CD的要求也变得越来越高。因此,docker等容器技术的普及也是势在必行。那么如何充分利用docker镜像的分层思想,提高镜像的复用程度,并减少每次生成镜像所花费的时间等问题,就需要我们深入思考。
3.2:解决方案
首先,可以将做一个三层的基础docker镜像,分别包括操作系统层、jdk等工具层、基础依赖jar包和配置文件层(这一层,需要用到使用dependency和resource插件,将那些通用的、基本不会变化的依赖包和资源文件独立打包置于这一层),备用。
其次,每次发布最新代码,只需要将所有可执行代码独立成一个jar包,并加入到前面提到的三层基础docker镜像中,作为第四层存在(这一层的内容主要用到maven-jar-plugin插件),然后发布即可。这样既提高了docker镜像的复用,也减少了每次更新代码时所打的jar包的臃肿程度。
四:插件应用举例
4.1:maven-jar-plugin 举例及部分说明
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<!-- 打包时包含的文件配置,在暗黑我的这个工程中,只打包 com 文件夹 -->
<includes>
<include>
**/com/**
</include>
</includes>
<archive>
<manifest>
<!-- 配置加入依赖包 -->
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<useUniqueVersions>false</useUniqueVersions>
<!-- Spring Boot 启动类(自行修改) -->
<mainClass>com.ccccit.springdockerserver.SpringDockerServerApplication</mainClass>
</manifest>
<manifestEntries>
<!-- 外部资源路径加入 manifest.mf 的 Class-Path -->
<Class-Path>resources/</Class-Path>
</manifestEntries>
</archive>
<!-- jar 输出目录 -->
<outputDirectory>${project.build.directory}/pack/</outputDirectory>
</configuration>
</plugin>
4.2:maven-dependency-plugin 举例及部分说明
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.2.0</version>
<!-- 复制依赖 -->
<executions>
<execution>
<!-- 这里的id可以随意写,与下面的goal无名称上的必然联系 -->
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<!-- 依赖包 输出目录 -->
<outputDirectory>${project.build.directory}/pack/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
对于maven-dependency-plugin插件而言,常用的"goal"包含以下几个内容,后续有时间也许会详细说明。
copy:拷贝指定jar包到指定目录,与当前工程的依赖没有关系
copy-dependencies:拷贝依赖jar包到指定目录
unpack:解压指定jar包到指定目录,与当前工程的依赖没有关系
unpack-dependencies:解压依赖jar包到指定目录
4.3:maven-resources-plugin 举例及部分说明
<!-- 在打包时,动态将maven的参数传给resource文件夹下的参数 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<encoding>UTF-8</encoding>
<!-- 当这里为true,那么resource文件夹下的配置文件,比如application.yml这些文件里面的${}包起来的内容就可以被pom文件中profiles标签下的对应名称部分行替换了 -->
<useDefaultDelimiters>true</useDefaultDelimiters>
</configuration>
<!-- 复制资源和bin文件夹 -->
<executions>
<execution>
<id>copy-resources</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<resources>
<resource>
<!-- 文件来源 -->
<directory>src/main/resources</directory>
</resource>
</resources>
<!-- 资源文件的输出目录 -->
<outputDirectory>${project.build.directory}/pack/resources</outputDirectory>
</configuration>
</execution>
<execution>
<id>copy-bin</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<resources>
<resource>
<!-- 文件来源 -->
<directory>src/main/bin</directory>
</resource>
</resources>
<!-- 资源文件的输出目录 -->
<outputDirectory>${project.build.directory}/pack/bin</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
以下内容是对上面提到的profiles替换的举例。比如下面我自定义了名为 letmesee.reason的标签,那么如果上面的useDefaultDelimiters标签值为true,那么在打包或编译阶段,maven会将resource文件夹下的所有配置文件的对应内容做替换
<!-- pom 文件的 profiles部分 -->
<profiles>
<profile>
<id>dev</id>
<properties>
<!-- 这里是让你自己随意定义属性用的,写成什么名字都无所谓,然后可以被resource中使用 -->
<letmesee.reason>dev</letmesee.reason>
<!-- 这里的 profiles.active 与其外层的profiles标签什么的毫无关系,仅仅是我碰巧起了个类似外层标签的名字,仅此而已 -->
<profiles.active>dev</profiles.active>
</properties>
<!-- 是否为默认的环境 -->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>shanxi</id>
<properties>
<letmesee.reason>shanxi</letmesee.reason>
<profiles.active>shanxi</profiles.active>
</properties>
</profile>
</profiles>
## application.yml 文件中的部分内容
spring:
profiles:
#要注意的是,active这里可以使用的是maven配置中<properties> 标签下的任何一个标签,哪怕我自定义了一个letmesee的标签也无所谓
active: ${letmesee.reason}
五:附录
Maven的内置参数
${basedir} 项目根目录
${project.build.directory} 构建终产物输出目录,缺省为target
${project.build.outputDirectory} 构建临时输出目录,缺省为target/classes
{project.build.finalName} 产出物名称,缺省为${project.artifactId}-${project.version}
${project.packaging} 打包类型,缺省为jar
${project.xxx} 当前pom文件的名为xxx节点内容