`

深入纠结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资源过滤的pom配置文件

    ### 解决Maven资源过滤的POM配置文件 在Maven项目中,资源文件(如配置文件、XML文件等)的处理非常重要。Maven通过`&lt;build&gt;`标签下的`&lt;resources&gt;`配置来管理这些资源文件的编译和打包过程。本文将详细解析如何...

    maven 过滤文件夹打包

    "maven 过滤文件夹打包"这个主题涉及到的是如何利用Maven的资源过滤功能来实现针对不同运行环境的配置文件打包。下面将详细解释这一过程。 在开发环境中,我们通常会有多种配置文件,比如`application-dev....

    maven资源包maven资源包

    Maven资源包是Java开发中的重要工具,它是一款项目管理和综合工具,由Apache软件基金会开发。Maven通过使用一种标准的目录结构和一个XML文件(pom.xml)来管理项目的构建、报告和文档,极大地简化了项目的构建过程。...

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

    maven资源过滤打包后文件变大的处理方法 Maven是一款流行的Java项目管理和构建工具,广泛应用于企业级项目中。但是,在使用Maven进行资源过滤和打包时,经常会遇到文件变大的问题。本文将详细介绍Maven资源过滤打包...

    maven资源文件

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

    Maven核心命令解析和Maven课程资源库大全

    Maven核心命令解析和Maven课程资源库大全Maven核心命令解析和Maven课程资源库大全Maven核心命令解析和Maven课程资源库大全Maven核心命令解析和Maven课程资源库大全Maven核心命令解析和Maven课程资源库大全Maven核心...

    maven 资源

    本资源包包含了Maven的一些常用包,这些包在Java开发过程中扮演着至关重要的角色。 首先,我们要理解Maven的基本概念。Maven是Apache软件基金会的一个开源项目,它的核心理念是“约定优于配置”。这意味着Maven通过...

    测试maven用到的资源

    在这个主题“测试maven用到的资源”中,我们将深入探讨Maven在测试环节中的应用和相关资源。 首先,Maven的核心概念之一是Project Object Model (POM),它是Maven项目的基本配置文件,通常命名为pom.xml。POM中包含...

    maven资源安装包

    ** Maven资源安装包详解 ** Maven,一个在IT领域广泛应用的项目管理和综合工具,以其强大的依赖管理和构建流程自动化功能而备受赞誉。标题中的“maven资源安装包”指的是一个包含Maven完整环境的压缩文件,它通常...

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

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

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

    本文将深入探讨“maven资源zip包连接阿里maven库”的相关知识点,以及如何利用这些资源来优化项目构建过程。 1. Maven的基本概念: Maven是Apache软件基金会开发的一款项目管理和综合工具。它通过一个XML文件(pom...

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

    Apache Maven 是一个强大的Java项目管理和综合工具,它简化了构建过程,通过标准化构建生命周期和依赖管理,使得开发者能够更高效地构建、测试和部署Java应用程序。Maven 3.3.9是Maven的一个稳定版本,它包含了多个...

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

    ### Maven资源路径设置详解 #### 一、Maven概述与资源管理 Maven是一个项目管理和构建工具,主要用于Java项目的构建和依赖管理。它通过一系列生命周期(lifecycle)、目标(goal)和插件来帮助开发者自动完成项目...

    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安装...

    Maven2资源和配置下载

    本篇文章将深入探讨"Maven2资源和配置下载"的主题,以及如何在MyEclipse环境中搭建私有仓库(私服)来管理和分发Maven文件。 首先,Maven2是Apache软件基金会开发的一款构建工具,它通过XML格式的POM(Project ...

    maven学习资源整理

    ** Maven学习资源整理** 在Java开发领域,Maven是一个不可或缺的构建工具,它极大地简化了项目的构建、管理和依赖管理过程。本资源包是为初学者和有经验的开发者准备的一系列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的继承与聚合 Maven支持项目间的继承和聚合。继承允许子项目共享父项目的配置,减少了重复代码。聚合则可以将...

    news jar包maven资源

    "news jar包maven资源"指的是包含与新闻相关的Java库的Maven仓库资源。这些资源可能包括了处理新闻数据、解析新闻格式、提供新闻API接口等功能的jar包。下面我们将详细讨论Maven、jar包以及如何在Maven项目中管理和...

    maven仓库资源包

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

Global site tag (gtag.js) - Google Analytics