在前面两篇文章中,咱们学习了Maven的基本使用方式和Maven项目的标准目录结构。接下来,咱们来看下Maven是若是管理项目中的资源文件的。html
Java项目的资源文件,主要用于存储系统的配置信息,以及提供系统集成的配置文件。项目中的资源文件夹下通常都存储了以.properties
为后缀的文件以及.xml
为后缀的文件,用于记录系统的上下文关系、log以及jdbc相关的配置信息。java
在咱们使用POM
管理项目的时候,咱们在进行打包的时候,须要将项目中的资源文件一块儿打包到最终的jar包中。因此,咱们须要将那些资源文件放置在Maven能够识别的目录下。数据库
在前一篇介绍Maven目录结构的文章中,咱们提到了在Maven的项目目录下,有一个默认的目录用于存放项目的资源文件:${basedir}/src/main/resources
。全部存放在这个目录下的资源文件,当Maven进行打包的时候,就会将该目录下的资源文件一块儿打包到jar包中。Maven打包的时候,会按照该${basedir}/src/main/resources
目录下资源文件组织的目录结构,在jar包的根目录下也会有相同的目录层次结构。apache
好比:bash
my-app |-- pom.xml `-- src |-- main | |-- java | | `-- com | | `-- mycompany | | `-- app | | `-- App.java | `-- resources | `-- META-INF | `-- application.properties `-- test `-- java `-- com `-- mycompany `-- app `-- AppTest.java
上面的项目打包成jar包之后,jar包中的目录结构以下所示:app
|-- META-INF | |-- MANIFEST.MF | |-- application.properties | `-- maven | `-- com.mycompany.app | `-- my-app | |-- pom.properties | `-- pom.xml `-- com `-- mycompany `-- app `-- App.class
咱们能够看到,资源文件application.properties
在咱们的项目中是在META-INFO
目录下,而打包之后,该文件仍旧是在该目录下,而META-INFO
目录是存放在jar包的根目录下的。maven
上面咱们只是介绍了咱们项目中系统须要的资源文件的存放位置,对于项目中的单元测试,也能够由一套本身的资源文件。这些资源文件存放的目录结构和上面的相似,只不过存放的目录名不一样。单元测试相关的资源文件存放在${basedir}/src/test/resources
目录下,和前面的目录对比,咱们能够发现,区别只是src目录下的main
目录和test
目录而已。这也是为何测试相关的代码和资源都是在test
目录下,而系统相关的代码和资源都存放在main
目录下,这样能够方便识别。ide
咱们能够看下一个包含单元测试资源文件的目录结构:单元测试
my-app |-- pom.xml `-- src |-- main | |-- java | | `-- com | | `-- mycompany | | `-- app | | `-- App.java | `-- resources | `-- META-INF | |-- application.properties `-- test |-- java | `-- com | `-- mycompany | `-- app | `-- AppTest.java `-- resources `-- test.properties
若是咱们须要在Java代码中访问项目的资源文件,好比上面的test.properties
文件,咱们只须要书写相似下面的代码:学习
InputStream is = getClass().getResourceAsStream( "/test.properties" );
咱们在写代码读取资源文件时,定位资源文件的位置的时候,须要参考实际该资源文件最终在jar包中存放的位置,而不是项目中的位置。按照上面提到的,在jar包中,是按照项目的resources
目录下的目录结构,在jar包的根目录下产生相同的目录结构的。对于上面的test.properties
文件,在jar包中就是存放在jar包的根目录下,因此咱们能够在代码中直接这么定位该文件的位置"/test.properties"
。
如今,咱们已经知道了Maven是如何管理资源文件的了。接下来,咱们来看下Maven提供的一种处理资源文件的机制,能够很方便的配置项目的资源。
有时候,咱们的资源文件中设置的值,只能在构建项目的时候才会被指定。为了完成这个需求,在Maven中能够为这个须要在构建的时候才能够肯定值的位置,放置一个占位符,来表示这个将来会被设置的值。经过使用${property}
的方式指定。其中property
能够是指定在pom.xml
文件中的值,或者是在setting.xml
文件中设置的值,或者是放在项目的filters目录(参考Maven的项目目录结构)下的外部的properties文件中的值,亦或是一个系统属性。这种方式在Maven中称为对资源文件的过滤。
为了使得Maven在将资源文件打包时对一个资源文件进行过滤处理,能够在pom.xml
中设置filtering
元素的值为true。
好比下面的例子:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mycompany.app</groupId> <artifactId>my-app</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>Maven Quick Start Archetype</name> <url>http://maven.apache.org</url> ... <build> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build> </project>
在上面的例子中,咱们在pom.xml
文件中添加了一个<build>...</build>
元素,在这个<build>
元素中,咱们定义了<resources>
元素来指定资源相关的配置,在<resources>
元素下的<resource>
元素中,咱们能够指定哪一个资源文件须要Maven进行过滤处理。在这里,咱们经过<directory>
元素指定了须要被Maven进行过滤的资源文件目录为src/main/resources
。<filtering>
元素指定这个资源目录是否须要被Maven进行过滤处理,默认是false,表示不进行处理。
当咱们须要引用定义在pom.xml
的文件中属性的时候,引用的属性的名字使用定义这个属性的XML元素的名字。使用pom
前缀表示项目根元素的别名。好比,${pom.name}
引用定义在pom.xml
文件中的项目的名字,${pom.version}
引用项目的版本,${pom.build.finalName}
引用项目的finalName
(finalName是项目最终被打包之后的名字)。相似的,若是是引用定义在setting.xml
文件中的名字,可使用${setting.localRepository}
名字来引用,引用的时候须要加上setting
前缀。
下面是一个使用Maven资源过滤的一个例子:
假设咱们有一个application.properties
文件,放在目录src/main/resources
下,文件中的内容以下:
application.name=${pom.name} application.version=${pom.version}
而后,咱们执行下面的命令来处理资源文件:
$ mvn process-resources
process-resources
命令会复制项目中的资源文件到目录target/classes
中,并进行过滤处理。
运行完之后,咱们能够看到application.properties
文件已经被实际的属性值替换了:
application.name=Maven Quick Start Archetype application.version=1.0-SNAPSHOT
接下来,咱们来看下怎样引用定义在外部的properties文件中的值。首先,咱们在Maven项目的的/src/main/filters
目录下添加一个properties文件filter.properties
,咱们在文件中定义一个属性键-值对:
my.filter.value=test
接下来,为了让Maven能够知道这个文件的存在,咱们须要在pom.xml
中引用这个文件:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mycompany.app</groupId> <artifactId>my-app</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>Maven Quick Start Archetype</name> <url>http://maven.apache.org</url> .... <build> <filters> <filter>src/main/filters/filter.properties</filter> </filters> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build> </project>
在上面的pom.xml
文件中,有一条定义在<filters>
元素中的语句<filter>src/main/filters/filter.properties</filter>
,指定了这个外部properties文件来对资源文件进行过滤处理。若是存在多个能够用于过滤的外部properties文件,能够定义多个<filter>
元素来指定。
下面,咱们在原来的application.properties
文件中添加一条属性来引用外部properties文件中的my.filter.value
的值:
application.name=${pom.name} application.version=${pom.version} message=${my.filter.value}
而后当咱们执行mvn process-resources
命令的时候,会使用外部properties文件中的值来替换application.properties
文件中的message
属性的${my.filter.value}
的值了。
除了咱们使用外部properties文件来实现上面的效果以外,咱们也可使用另一种方式来达到上面同样的效果。只须要在pom.xml
文件中定义<properties></properties>
元素来定义咱们须要过滤的属性,好比上面的my.filter.value
属性:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mycompany.app</groupId> <artifactId>my-app</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>Maven Quick Start Archetype</name> <url>http://maven.apache.org</url> ... <build> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build> <properties> <my.filter.value>test</my.filter.value> </properties> </project>
上面的pom.xml
文件中,咱们在<properties></properties>
元素中定义了一个名为<my.filter.value>
的元素,这样,咱们就能够在资源文件中直接引用这个元素中定义的属性值了。达到和上面使用外部properties文件同样的效果。
下面,咱们看下如何得到系统级别的属性吧。
被Maven过滤的资源文件,能够得到系统级别的属性,以及Java内建的属性,好比java.version
和java.home
。咱们也能够得到命令行下传递过来的属性值,经过-D
选项来指定:
咱们修改以前的application.properties
文件,添加如下的内容:
java.version=${java.version} command.line.prop=${command.line.prop}
如今,咱们执行下面的命令:
$ mvn process-resources "-Dcommand.line.prop=hello world"
上面的命令,在命令行上经过-D
选项指定了一个属性值,因此咱们在过滤资源文件的时候会得到这个值,并进行替换。
执行之后,在target/classes
目录下的application.properties
文件中,会变成这样:
java.version=1.7.0_79 command.line.prop=hello world
好了,到这里,咱们已经把Maven对资源文件过滤的内容介绍的差很少了。接下来,咱们来看一个使用Maven资源文件过滤的实际例子:
如今咱们有这样一个问题,咱们在开发过程当中须要多套配置数据来配置开发环境,好比数据库地址的配置等信息。咱们须要在多个开发情景下进行切换,若是咱们将配置信息写死在资源文件中,那么在咱们切换的时候,会比较繁琐,还可能出现拼写错误,特别是涉及到IP地址的修改的时候。因此,咱们能够定义两套配置方案,经过Maven的资源过滤机制,能够很方便的进行切换。
首先,假设咱们有开发和测试两个开发情景,那么,咱们能够定义两个对应的properties文件:dev-filter.properties
和test-filter.properties
。把这两个文件放在项目的filters
目录下,做为外部properties文件。
两个文件的定义以下:
# dev-filter.properties db.url=192.168.31.101 # test-filter.properties db.url=192.168.32.102
如今,加上咱们的数据库链接的配置是放在jdbc.properties
这个资源文件中:
jdbc.url=${db.url}
那么,咱们须要在pom.xml
中指定须要被过滤的资源文件,以及外部的properties文件:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mycompany.app</groupId> <artifactId>my-app</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>Maven Quick Start Archetype</name> <url>http://maven.apache.org</url> .... <build> <filters> <filter>src/main/filters/filter-${env}.properties</filter> </filters> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build> </project>
如今,咱们只是能够对jdbc.properties
这个资源文件进行过滤了,可是,咱们注意到,在上面的pom.xml
文件中,在定义外部properties文件的时候,使用了一个名为${env}
的变量,因此,咱们接下来要定义这个env
变量,来实现不一样开发情景的切换。咱们使用了Maven的profile
来实现:
<profiles> <!-- 开发环境,默认激活 --> <profile> <id>dev</id> <properties> <env>dev</env> </properties> <activation> <activeByDefault>true</activeByDefault> </activation> </profile> <!-- 测试环境 --> <profile> <id>test</id> <properties> <env>test</env> </properties> </profile> </profiles>
上面的代码中定义了变量env
,将上面的代码放到pom.xml
文件中,就能够实现开发环境和测试环境的切换了。
咱们能够用下面的命令来进行切换:
$ mvn clean package -Pdev # 将Maven切换到开发情景 $ mvn clean package -Ptest # 将Maven切换到测试情景
好了,对Maven的资源的处理,就介绍到这里。若是您以为文章写的还行,不妨动动您的鼠标,点个赞吧~