maven-resources-plugin 处理资源文件
目标:resources, testResources
指定resources插件读取和写入文件的字符编码,比如ASCII,UTF-8或UTF-16。
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
默认情况下,Maven会从项目的src/main/resources目录下查找资源。如果你的资源不在此目录下,可以用<resources>标签指定,同时也支持多个目录。
<build>
<resources>
<resource>
<directory>src/main/resources1</directory>
</resource>
<resource>
<directory>src/main/resources2</directory>
</resource>
</resources>
</build>
有的时候,资源文件中存在变量引用,可以使用<filtering>标签指定是否替换资源中的变量。变量的来源为pom文件中的<properties>标签中定义的变量。也可以在<build>中定义过滤器资源,还可以使用<includes>和<excludes>来精细控制。
<build>
<filters>
<filter>filter-values.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.txt</include>
<include>**/*.rtf</include>
</includes>
<excludes>
<exclude>**/*.bmp</exclude>
<exclude>**/*.jpg</exclude>
<exclude>**/*.jpeg</exclude>
<exclude>**/*.gif</exclude>
</excludes>
</resource>
</resources>
</build>
如果资源中本来存在{}字符,不需要被替换,可以在前加\,并在<configuration>中使用<escapeString>。
另外,目录下存在二进制文件,需要排除,也可以在<configuration>中使用<nonFilteredFileExtensions>根据后缀来过滤。
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<encoding>UTF-8</encoding>
<escapeString>\</escapeString>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>pdf</nonFilteredFileExtension>
<nonFilteredFileExtension>swf</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>
AppAssembler Maven 插件
AppAssembler Maven 插件 中的一段配置,用于把 Spring Boot 应用打成 可解压的目录包(而非 fat-jar)。
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>2.1.0</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>assemble</goal>
</goals>
</execution>
</executions>
<configuration>
<configurationDirectory>conf</configurationDirectory>
<configurationSourceDirectory>src/main/resources</configurationSourceDirectory>
<copyConfigurationDirectory>true</copyConfigurationDirectory>
<includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
<repositoryLayout>flat</repositoryLayout>
<repositoryName>lib</repositoryName>
<useWildcardClassPath>true</useWildcardClassPath>
<!-- 避免二次过滤 -->
<filterConfigurationDirectory>false</filterConfigurationDirectory>
<environmentSetupFileName>init.sh</environmentSetupFileName>
<assembleDirectory>${project.build.directory}/${project.artifactId}-${project.version}</assembleDirectory>
<platforms>
<platform>unix</platform>
</platforms>
<programs>
<program>
<id>${project.artifactId}</id>
<mainClass>com.MyApiApplication</mainClass>
<platforms>
<platform>unix</platform>
</platforms>
</program>
</programs>
</configuration>
</plugin>
逐行解释如下:
配置项 | 含义 |
---|---|
<configurationDirectory>conf</configurationDirectory> |
在最终目录里创建一个 conf/ 目录,用来存放配置文件。 |
<configurationSourceDirectory>src/main/resources</configurationDirectory> |
把 src/main/resources 下的所有文件原样复制到 conf/。 |
<copyConfigurationDirectory>true</copyConfigurationDirectory> |
启用 上述复制。设为 false 就不会复制资源文件。 |
<includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath> |
启动脚本会把 conf/ 目录加入 JVM 的 classpath,运行时能直接读取里面的配置。 |
<repositoryLayout>flat</repositoryLayout> |
所有依赖 jar 平铺放在 lib/ 目录,而不是按 groupId 分多级目录。 |
<repositoryName>lib</repositoryName> |
依赖 jar 所在的目录名字,最终生成 /lib。 |
<useWildcardClassPath>true</useWildcardClassPath> |
启动脚本用通配符 lib/* 加载所有 jar,避免列出每个文件名。 |
<filterConfigurationDirectory>false</filterConfigurationDirectory> |
关闭 对 conf/ 目录的 Maven 资源过滤,防止二进制文件(pfx、pem 等)被编码。(没法区分目录来进行filter) |
<environmentSetupFileName>init.sh</environmentSetupFileName> |
在 bin/ 目录额外生成 init.sh 脚本,可写环境变量、前置命令等。 |
这段配置让 AppAssembler 把 src/main/resources
原样拷到 conf/
并加入 classpath,依赖平铺到 lib/
,且不对二进制文件做过滤,最终得到一个可解压、可执行、目录结构的部署包。
启动脚本
<programs>
<program>
<id>${project.artifactId}</id>
<mainClass>com.MyApiApplication</mainClass>
<platforms>
<platform>unix</platform>
</platforms>
</program>
</programs>
-
在
target/my-api-1.0.0/bin/my-api
(Unix 脚本)中:#!/bin/sh
由 AppAssembler 自动生成
CLASSPATH="conf:lib/*"
exec java -classpath "CLASSPATH" com.myApplication "@"
最终目录结构
target/my-api-1.0.0/
├── bin/
│ ├── my-api # 启动脚本
│ └── init.sh # 环境脚本
├── conf/
│ ├── application.yml # 来自 target/classes/tmp/
│ ├── server.pfx # 证书原样复制
│ └── logback.xml
└── lib/
├── spring-boot-*.jar
└── your-app-*.jar
项目运行
脚本运行
cd /Users/manka/project/my-api/target/my-api-0.0.1-SNAPSHOT
./bin/my-api
java指令运行
cd /Users/manka/project/my-api/target/my-api-0.0.1-SNAPSHOT
java -cp "conf:lib/*" -Dspring.config.location=optional:classpath:/,file:conf/ com.MyApiApplication
插件执行顺序
maven-resources-plugin
先于 appassembler-maven-plugin
执行 ;
前者在 process-resources 阶段完成资源复制,后者在 package 阶段把已生成的资源再搬运到最终目录。
插件 | 默认绑定阶段 | 作用 |
---|---|---|
maven-resources-plugin |
process-resources |
把 src/main/resources → target/classes |
appassembler-maven-plugin |
package |
把 target/classes (或你指定的目录)→ target/artifactId-version/conf/ |
两者结合使用
需求:
1、想要区分目录的文件进行filter, 其他目录不进行filter。
2、项目打包脚本用到了appassembler-maven-plugin。
解决:
<resources> 先过滤/复制,AppAssembler 再二次搬运;两者职责互补,可同时使用,只需确保 AppAssembler 的 filterConfigurationDirectory 设为 false 即可保护二进制文件.
-
<resources> 负责把 源码阶段 的文件(src/main/resources 等)原样或过滤后复制到 target/classes;
-
<resource> <directory>src/main/resources/config/</directory> <filtering>true</filtering> <includes> <include>**/*</include> </includes> <targetPath>${project.build.outputDirectory}/tmp/config</targetPath> </resource> <resource> <directory>${project.basedir}/src/main/resources/cert</directory> <includes> <include>*</include> </includes> <targetPath>${project.build.outputDirectory}/tmp/cert</targetPath> </resource> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>appassembler-maven-plugin</artifactId> <version>2.1.0</version> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>assemble</goal> </goals> </execution> </executions> <configuration> <configurationDirectory>conf</configurationDirectory> <configurationSourceDirectory>${project.build.outputDirectory}/tmp</configurationSourceDirectory> <copyConfigurationDirectory>true</copyConfigurationDirectory> <includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath> <repositoryLayout>flat</repositoryLayout> <repositoryName>lib</repositoryName> <useWildcardClassPath>true</useWildcardClassPath> <filterConfigurationDirectory>false</filterConfigurationDirectory> <environmentSetupFileName>init.sh</environmentSetupFileName> <assembleDirectory>${project.build.directory}/${project.artifactId}-${project.version}</assembleDirectory> <platforms> <platform>unix</platform> </platforms> <programs> <program> <id>${project.artifactId}</id> <mainClass>com.MyApplication</mainClass> <platforms> <platform>unix</platform> </platforms> </program> </programs> </configuration> </plugin>appassembler-maven-plugin 再把 已生成的 target/classes 或你指定的其它目录,二次拷贝到最终打包目录(conf/、lib/、bin/)。