`

深入纠结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资源包3.6.3

    maven资源包3.6.3

    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支持项目间的继承和聚合。继承允许子项目共享父项目的配置,减少了重复代码。聚合则可以将...

    Maven2资源和配置下载

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

    idea+maven+springmvc 登录过滤器

    创建登录过滤器的目的是在用户访问受保护的资源之前进行身份验证。过滤器在Spring MVC中扮演着请求预处理的角色,可以在请求到达控制器之前进行拦截,进行必要的处理,如检查用户是否已经登录。以下是构建登录过滤器...

    maven资源包maven资源包

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

    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包解压...

    news jar包maven资源

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

Global site tag (gtag.js) - Google Analytics