`

深入纠结maven的资源过滤

阅读更多
关于maven的资源过滤,官方文档有个例子:

<project>
  ...
  <build>
    ...
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
        <includes>
          <include>**/*.xml</include>
        </includes>
      </resource>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>false</filtering>
        <excludes>
          <exclude>**/*.xml</exclude>
        </excludes>
      </resource>
      ...
    </resources>
    ...
  </build>
  ...
</project>


刚开始我很困惑:
include=true与exclude=false难道不是等价的吗?这样配置不是重复了吗?

后来通过这篇文章这篇文章找到正确的理解方式:
1.在src/main/resources目录下,xml文件都是资源文件,且需要被过滤
2.在src/main/resources目录下,除了xml文件以外的其他文件,也是资源文件,但它们不需要被过滤

但这样,好像还是有点绕。

看看源码吧。

ResourcesMojo类的execute方法为入口:

public void execute()
        throws MojoExecutionException
    {
			//...
            mavenResourcesFiltering.filterResources( mavenResourcesExecution );
			//...

    }


找到org.apache.maven.shared.filtering.DefaultMavenResourcesFiltering.filterResources:


    public void filterResources( MavenResourcesExecution mavenResourcesExecution )
        throws MavenFilteringException {
		
		
		
		
for ( Resource resource : mavenResourcesExecution.getResources() )
        {


            String targetPath = resource.getTargetPath();

            File resourceDirectory = new File( resource.getDirectory() );

            Scanner scanner = buildContext.newScanner( resourceDirectory, ignoreDelta );

			//扫描
            setupScanner( resource, scanner, mavenResourcesExecution.isAddDefaultExcludes() );

            scanner.scan();

			//获取符合条件的文件
            List<String> includedFiles = Arrays.asList( scanner.getIncludedFiles() );


            for ( String name : includedFiles )
            {

                File source = new File( resourceDirectory, name );

                File destinationFile = getDestinationFile( outputDirectory, targetPath, name, mavenResourcesExecution );

                boolean filteredExt =
                    filteredFileExtension( source.getName(), mavenResourcesExecution.getNonFilteredFileExtensions() );

				//替换和拷贝
                mavenFileFilter.copyFile( source, destinationFile, resource.isFiltering() && filteredExt,
                                          mavenResourcesExecution.getFilterWrappers(),
                                          mavenResourcesExecution.getEncoding(),
                                          mavenResourcesExecution.isOverwrite() );
            }
	}
}


步骤很清晰:
1.扫描指定目录,找出哪些文件是符合条件的
2.遍历符合条件的文件,如果需要过滤则进行过滤否则保持原样,最后拷贝到目标文件夹。

有几个关键的参数:
resource.isFiltering():是否过滤
mavenResourcesExecution.isOverwrite():是否覆盖

看看如何定义为“符合条件的文件”:

org.codehaus.plexus.util.DirectoryScanner.scan() {

        if ( isIncluded( "", tokenizedEmpty ) )
        {

            if ( !isExcluded( "", tokenizedEmpty ) )
            {
                if ( isSelected( "", basedir ) )
                {
                    dirsIncluded.addElement( "" );
                }
                else
                {
                    dirsDeselected.addElement( "" );
                }
            }
            else
            {
                dirsExcluded.addElement( "" );
            }
        }
        else
        {
            dirsNotIncluded.addElement( "" );
        }
}


看到这里就明白了:
满足<include></include>的条件,且不满足<exclude></exclude>的条件,就是“符合条件的文件”,也就是资源文件。
由代码也可看出,如果某个文件同时满足include和exclude,则结果为exclude。也就是exclude的优先级高。

再看看DirectoryScanner的注释:

 * The segments of the name and the pattern are then matched against each
 * other. When '**' is used for a path segment in the pattern, it matches
 * zero or more path segments of the name.
 * <p/>
 * There is a special case regarding the use of <code>File.separator</code>s
 * at the beginning of the pattern and the string to match:<br>
 * When a pattern starts with a <code>File.separator</code>, the string
 * to match must also start with a <code>File.separator</code>.
 * When a pattern does not start with a <code>File.separator</code>, the
 * string to match may not start with a <code>File.separator</code>.
 * When one of these rules is not obeyed, the string will not
 * match.
 * <p/>
 * When a name path segment is matched against a pattern path segment, the
 * following special characters can be used:<br>
 * '*' matches zero or more characters<br>
 * '?' matches one character.
 * <p/>
 * Examples:
 * <p/>
 * "**\*.class" matches all .class files/dirs in a directory tree.
 * <p/>
 * "test\a??.java" matches all files/dirs which start with an 'a', then two
 * more characters and then ".java", in a directory called test.
 * <p/>
 * "**" matches everything in a directory tree.
 * <p/>
 * "**\test\**\XYZ*" matches all files/dirs which start with "XYZ" and where
 * there is a parent directory called test (e.g. "abc\test\def\ghi\XYZ123").
 * <p/>


从注释中可知:

1.当<resouces>没有指定include时,默认为包括目录下所有文件; 如果没有指定exclude时,默认为不排除任一文件。
2.**表示匹配任意个目录
例如**/*.xml匹配以下:
a.xml
b/b.xml
c/d/f.xml

最后举个生产上的例子:
需求:
1.所有配置项都在properties/config.properties文件里,打包时需要根据不同的profile替换成真正的数值(例如数据库地址,生产跟测试是不同的)
2.其他spring文件里引用config.properties的变量(通过org.springframework.beans.factory.config.PropertyPlaceholderConfigurer),不需要替换成真正的值。这样的好处就是万一生产上要改配置,就只改config.properties,不需要到各个spring配置文件里修改
3.eboxx-client.xml也要过滤,因为它不是基于spring的,不能引用config.properties的变量

配置:

    
 <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
        <includes>
          <include>properties/config.properties</include>
		  <include>eboxx-client.xml</include>
        </includes>
      </resource>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>false</filtering>
      </resource>


模拟一下maven进行资源过滤的过程:
1.读取第一个resource标签,找到符合条件的文件:config.properties文件和eboxx-client.xml
2.根据filtering=true得知,这两个文件需要过滤
3.过滤完成后,拷贝文件到默认目录(${project.build.outputDirectory},也就是target/classes目录)

4.读取第二个标签,由于没有指定include和exclude,所有文件都符合条件
5.根据filtering=false得知,这些文件不需要过滤
6.开始拷贝文件。拷贝过程中发现config.properties和eboxx-client.xml已经在默认目录存在了,由于overwrite默认为false,也就是不覆盖
7.结束

关于overwrite的默认值可以在ResourcesMojo.java中找到:

    /**
     * Overwrite existing files even if the destination files are newer.
     *
     * @since 2.3
     */
    @Parameter( property = "maven.resources.overwrite", defaultValue = "false" )
    private boolean overwrite;


事实上,为满足上面的需求,有个简单的办法:

1.pom.xml
<properties>
	<p.jdbc.username>RTFM</p.jdbc.username>
</properties>


2.config.properties
jdbc_user=${p.jdbc.username}


3.beans.xml
 <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> 
     <property name="username" value="${jdbc_user}" />
 </bean>


在配置资源过滤时,默认过滤所有文件。
由于beans.xml与pom.xml的变量名不一样,因为即使beans.xml被过滤了,里面的变量也不会被替换。

这样,或许人生会更简单一些^_^

1
1
分享到:
评论

相关推荐

    maven资源包maven资源包

    maven资源包maven资源包maven资源包maven资源包maven资源包maven资源包maven资源包maven资源包maven资源包maven资源包

    解决Maven资源过滤的pom配置文件

    举例说明: &lt;directory&gt;src/main/java **/*.properties **/*.xml &lt;filtering&gt;false &lt;/resource&gt;

    maven 过滤文件夹打包

    工程运行环境有研发,测试和生产,不同的运行环境配置不同,maven 打包时指定文件目录,使用指定的文件夹下的配置文件。

    maven资源文件

    maven构建webAPP工程时加入此文件可以快速构建,减少等待

    maven资源 apache-maven-3.3.9-bin.zip

    maven资源 apache-maven-3.3.9-bin.zip

    Maven全版本资源,Maven 3.0.5-3.8.5,每个版本包含4个文件,Maven3全资源打包下载,Maven全集

    所有资源都在一起,,打包下载,所有资源都在一起,,打包下载,所有资源都在一起,,打包下载,所有资源都在一起,,打包下载,所有资源都在一起,,打包下载,所有资源都在一起,,打包下载,所有资源都在一起,,...

    maven资源库

    maven资源库,海量下载,java开发必备,有需要的可以下载。

    maven 资源

    一些maven常用包

    maven安装maven安装maven安装maven安装maven安装

    maven安装maven安装maven安装maven安装maven安装maven安装maven安装maven安装maven安装maven安装maven安装maven安装maven安装maven安装maven安装maven安装maven安装maven安装maven安装maven安装maven安装maven安装...

    测试maven用到的资源

    测试maven用到的资源

    maven资源过滤打包后文件变大的处理方法

    maven目前在web上面的使用方式很普遍,而打包的方式也存在很多方式,下面这篇文章主要给大家介绍了关于maven资源过滤打包后文件变大的处理方法,文中通过示例代码介绍的非常详细,需要的朋友可以参考下

    maven资源zip包连接阿里maven库各种包齐全

    最全的maven资源包连接阿里资源库包括各大框架包邮件包oss上传包等等

    深入浅出maven3

    maven是什么 maven这个词可以翻译为“知识的积累”,也可以翻译为“专家”或“内 行”。作为apache组织中的一个颇为成功的开源项目,maven主要服务于基于 java平台的项目构建、依赖管理和项目信息管理。 maven...

    logging-log4j2-log4j-2.15.0-rc2.zip maven 资源库

    针对Log4j 2 远程代码执行漏洞,需要用到的升级资源包,适用于maven资源库,包括log4j,log4j-core,log4j-api,log4j-1.2-api,log4j-jpa等全套2.15.0 maven资源库jar包。如果是maven本地仓库使用,需要将zip包解压...

    maven仓库资源包

    包含常用的maven jar包有需要请下载..

    maven资源路径设置方法,以及配置阿里云资源

    配置maven本地仓库以及路径,还有一个资源是修改Eclipse中的setting.xml最好一起参考,都是我上传的资源

    开源工具Maven3.9.4版本压缩包

    Maven3.9.4版本压缩包,仅供学习参考,更新版本请前往Maven官方下载;Maven3.9.4版本压缩包,仅供学习参考,更新版本请前往Maven官方下载;Maven3.9.4版本压缩包,仅供学习参考,更新版本请前往Maven官方下载;Maven...

    news jar包maven资源

    news jar包maven资源

    maven资源安装包

    maven:Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。主要用于大型项目的jar包管理,和多个互相依赖的项目的管理。

    chm版本Maven教程

    Maven本地资源库 Maven中央存储库 如何从Maven远程存储库下载? Maven添加远程仓库 Maven依赖机制 定制库到Maven本地资源库 使用Maven创建Java项目 使用Maven创建Web应用程序项目 Maven POM Maven 构建生命周期 ...

Global site tag (gtag.js) - Google Analytics