灵活使用Maven Profile
项目中一直应用Maven的profile特性解决不同环境的部署问题。最近在尝试解决本地调试环境的时候碰到一些问题,顺便仔细研究了一下。因为项目仍然在用普通SpringMVC架构,没有切换到Spring Boot,所以例子以SpringMVC为基础。
这里就不介绍Profile的基础知识了,不了解的请找相关资料查一下。
1 Profile的基础使用
我们常见的两种使用Profile的方法:占位符替换和文件复制。
1.1 Profile定义
在项目的pom.xml中定义不同的profile,以数据库主机地址为例。
|
<profiles> <profile> <id>dev</id> <properties> <active.profile>dev</active.profile> <database.host>localhost</database.host> </properties> </profile> <profile> <id>test</id> <properties> <active.profile>test</active.profile> <database.host>test.codestory.tech</database.host> </properties> </profile> <profile> <id>prod</id> <properties> <active.profile>prod</active.profile> <database.host>prod.codestory.tech</database.host> </properties> </profile> </profiles> |
1.2 替换占位符方法
为了简化,将本位涉及的所有参数保存到 src/main/resources/config下的props.properties 文件中,格式为
|
database.pool.host=${database.host} |
在pom.xml中定义 resources 插件,定制资源复制的动作。
|
<build> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering><!-- 替换占位符 --> </resource> </resources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> <configuration> <encoding>UTF-8</encoding> <overwrite>true</overwrite><!-- 目标文件存在时覆盖 --> </configuration> </plugin> </plugins> </build> |
执行 maven 命令,指定 profile 复制资源,复制的资源在目录 target/classes 下。分别用三个不同的profile执行mvn 命令后结果如下:
mvn clean resources:resources -P dev
|
database.pool.host=localhost |
mvn clean resources:resources -P test
|
database.pool.host=test.codestory.tech |
mvn clean resources:resources -P prod
|
database.pool.host=prod.codestory.tech |
1.3 复制文件方法
除了使用properties替换占位符的方法,还可以分别为每个profile编写文件,打包时根据选择的profile进行复制。
创建各个profile需要的配置文件,在src/main/resources 中创建目录 profiles ,并在其中创建三个子目录:dev/test/prod,每个子目录中创建一个props.properties文件,内容分别为
src/main/resources/profiles/dev/props.properties
|
database.pool.host=localhost |
src/main/resources/profiles/test/props.properties
|
database.pool.host=test.codestory.tech |
src/main/resources/profiles/prod/props.properties
|
database.pool.host=prod.codestory.tech |
为了测试resources-plugin的参数 overwrite ,我们将 src/main/resources/config/props.properties 内容增加一行,变为
|
database.pool.host=${database.host} database.pool.port=3306 |
在pom.xml中修改resources部分配置
|
<resources> <resource> <directory>src/main/resources</directory> <excludes> <exclude>profiles/**</exclude> </excludes> <filtering>true</filtering><!-- 替换占位符 --> </resource> <resource> <directory>src/main/resources/profiles/${active.profile}</directory> <targetPath>config</targetPath> <filtering>false</filtering><!-- 不替换占位符,直接复制 --> </resource> </resources> |
同样执行maven resources命令后查看文件内容,
mvn clean resources:resources -P dev
|
database.pool.host=localhost |
注意属性文件中没有 database.pool.port=3306 这一行,说明是复制文件的结果,而不是直接替换占位符。
2 同时使用多个profile
前面的例子足够简单,也能解决大部分场景下打包的问题。扩展一下场景,看看问题如何解决?
2.1 本地用test环境调试
为了场景需要,假设props.properties文件中还有一个参数,用于记录附件的保存路径(为了场景假设的,使用分布式文件服务器或webdav等技术的同学请忽视)。
|
database.pool.host=${database.host} filesystem.path.root=${path.root} |
现在测试同学在测试环境发现了BUG,开发需要访问test环境数据库进行联调,但附件保存路径不同,本地不能直接使用 -P test。使用Tomcat远程调试的同学也请绕道一下。另外还有一个简单的办法,修改一下pom.xml中的profile[test]中path.root参数即可解决。不过为了研究profile,也不用这个太简单的方案。
2.2 多个profile 替换占位符的方法
解决的思路是保持原有的profile配置信息不变,额外选中一个本地调试用的profile,替换其中少量参数。
pom.xml中profiles内容修改为
|
<profiles> <profile> <id>local</id> <properties> <active.profile>local</active.profile> <path.root>d:/develop/attachments</path.root> </properties> </profile> <profile> <id>dev</id> <properties> <active.profile>dev</active.profile> <database.host>localhost</database.host> <path.root>d:/develop/attachments</path.root> </properties> </profile> <profile> <id>test</id> <properties> <active.profile>test</active.profile> <database.host>test.codestory.tech</database.host> <path.root>/app/attachments</path.root> </properties> </profile> <profile> <id>prod</id> <properties> <active.profile>prod</active.profile> <database.host>prod.codestory.tech</database.host> <path.root>/app/attachments</path.root> </properties> </profile> </profiles> |
使用多个profile,在-P参数后,只需要用逗号分隔即可。我的目的是用local中的参数替换test中同名参数,所以将 local放在后面。(需要在pom.xml中注释掉<directory>src/main/resources/profiles/${active.profile}</directory>这个resource定义)
mvn clean resources:resources -P test,local
|
database.pool.host=test.codestory.tech filesystem.path.root=/app/attachments |
发现文件内容并没有按照我预期的目标替换,而是仍然用了test的参数。在网上搜索,在百度知道一个回答中找到了答案 https://zhidao.baidu.com/question/139071460381210925.html ,【它是根据profile定义的先后顺序来进行覆盖取值的,然后后面定义的会覆盖前面定义的。】
因此,修改 pom.xml中profiles的顺序,将local放到最后,重新执行命令
mvn clean resources:resources -P test,local
|
database.pool.host=test.codestory.tech filesystem.path.root= d:/develop/attachments |
2.3 多个profile复制文件
再来试试复制文件的方法是否继续有效。为了测试方便,在profiles/{active.profile}的目录下,分别放置了一个不同的属性文件,文件名含profile名,分别为env-dev.properties/env-test.properties /env-prod.properties。
首先,只用一个profile测试
mvn clean resources:resources -P test
在target/classes/config 目录中可以看到两个文件 env-test.properties和props.properties,说明复制文件成功;查看文件内容,可以发现都是从 src/main/resources/profiles/test 目录复制而来。
测试两个profile,再检查目录 target/classes/config,发现只有一个文件 props.properties,并且内容是 src/main/resource/config/props.properties文件替换占位符的结果。
mvn clean resources:resources -P test,local
|
database.pool.host=test.codestory.tech filesystem.path.root=d:/develop/attachments |
为了测试原因,在 src/main/resource/config/props.properties 中增加一个参数activeProfiles,文件内容为:
|
database.pool.host=${database.host} filesystem.path.root=${path.root} active.profiles=${active.profile} |
mvn clean resources:resources -P test,local
|
database.pool.host=test.codestory.tech filesystem.path.root=d:/develop/attachments active.profiles=local |
原因在于:根据优先级,参数active.profile只保留了最后一个 local,所以无法实现拷贝 test 目录下文件的效果。
2.4 修改profile复制文件方法
在maven的pom规范中,在每个profile中还可以定义build参数,因此将pom.xml中profiles部分内容修改为
|
<profiles> <profile> <id>dev</id> <properties> <active.profile>dev</active.profile> <database.host>localhost</database.host> <path.root>d:/develop/attachments</path.root> </properties> <build> <resources> <resource> <directory>src/main/resources/profiles/dev</directory> <targetPath>config</targetPath> <filtering>false</filtering> </resource> </resources> </build> </profile> <profile> <id>test</id> <properties> <active.profile>test</active.profile> <database.host>test.codestory.tech</database.host> <path.root>/app/attachments</path.root> </properties> <build> <resources> <resource> <directory>src/main/resources/profiles/test</directory> <targetPath>config</targetPath> <filtering>false</filtering> </resource> </resources> </build> </profile> <profile> <id>prod</id> <properties> <active.profile>prod</active.profile> <database.host>prod.codestory.tech</database.host> <path.root>/app/attachments</path.root> </properties> <build> <resources> <resource> <directory>src/main/resources/profiles/prod</directory> <targetPath>config</targetPath> <filtering>false</filtering> </resource> </resources> </build> </profile> <profile> <id>local</id> <properties> <active.profile>local</active.profile> <path.root>d:/develop/attachments</path.root> </properties> </profile> </profiles> |
可以看到,在每个profile中增加了文件复制的内容。同之前配置的区别在于:不再使用变量 ${active.profile},而是直接写profile的名称。删除之前定义的<directory>src/main/resources/profiles/${active.profile}</directory>,再次测试
mvn clean resources:resources -P test,local
在target/classes/config 目录中可以看到两个文件 env-test.properties和props.properties,说明复制文件成功。
当然这时候想达到本节开始的场景:本地使用test数据库调试,需要拆分props.properties为两个文件,分别处理了:数据库信息放一个文件(使用复制文件的方法),文件目录放另一个文件(使用替换占位符的方法)。
3 尝试在项目配置文件中记录所使用的Profiles
前面的例子中,使用active.profiles=${active.profile}记录的值,只有最后一个profile的id。如果想记录所有使用到的profile,希望配置文件中的值是active.profiles=test,local。该怎么做呢?
经过测试,发现maven有一个内置参数是 activeProfiles。将原始配置文件修改为 active.profiles=${activeProfiles}
mvn clean resources:resources -P test,local
|
active.profiles=[Profile {id: test, source: pom}, Profile {id: local, source: pom}] |
在网上搜索了很久,没发现用什么办法能够处理${activeProfiles}的输出值。不过文本也足够简单,可以在项目中读出这个字符串后进行后续处理,比如处理为: active.profiles=test,local
4 在Maven的settings.xml中定义profile
除了项目pom.xml中定义profile,还可以在maven/conf/settings.xml中定义。为了测试profile的优先级,定义了两个profile,并且新加了一个属性active.profile.label,并且将local和test的顺序互换。
|
<profiles> <profile> <id>local</id> <properties> <active.profile>local</active.profile> <active.profile.label>settings profile local</active.profile.label> <filesystem.path.root>d:/develop/attachments</filesystem.path.root> </properties> </profile> <profile> <id>test</id> <properties> <active.profile>test</active.profile> <active.profile.label>settings profile test</active.profile.label> </properties> </profile> </profiles> |
创建一个profiles.txt文件用于输出,原始内容(为了区别输出内容,增加了#字符分隔行)
|
############################################### active.profiles=${activeProfiles} ############################################### active.profile.label=${active.profile.label} ############################################### |
使用命令
mvn clean resources:resources -P test,local
|
############################################### active.profiles=[Profile {id: test, source: pom}, Profile {id: local, source: pom}, Profile {id: local, source: settings.xml}, Profile {id: test, source: settings.xml}] ############################################### active.profile.label=settings profile test ############################################### |
由此可见,当同时在pom.xml和settins.xml中定义了相同id的profile,其加载顺序是先依次加载 pom.xml中的Profiles,再加载settings.xml中的profiles。当定义了相同名称的属性时,很可能会导致意外的结果。
灵活使用Maven Profile的更多相关文章
- 项目实现不同环境不同配置文件-maven profile
最近接触的项目都是在很多地方都落地的项目,需要支持不同的环境使用不同的配置文件.一直以来都以为是人工的去写不同的配置文件,手动的去修改运用的配置文件.感觉自己还是太low呀.maven的使用的还停留在 ...
- 使用maven profile实现多环境可移植构建(转自CSDN)
使用maven profile实现多环境可移植构建 标签: maven profilemaven自动构建maven自动部署maven可移植构建持续集成 2014-04-25 23:37 26905人阅 ...
- 通过maven profile 打包指定环境配置
背景 最近换了个新公司接手了一个老项目,然后比较坑的是这个公司的项目都没有没有做多环境打包配置,每次发布一个环境都要手动的去修改配置文件.今天正好有空就来配置下. 解决这个问题的方式有很多,我这里挑选 ...
- maven profile实现多环境配置
每次项目部署上线都需要手动去修改配置文件(比如数据库配置,或者一个自定义的配置)然后才能打包,很麻烦,网上找到 maven profile可以完成这个工作,记录如下: 环境:eclipse + spr ...
- 在eclipse激活maven profile配置
profile简介 profile可以让我们定义一系列的配置信息,然后指定其激活条件.这样我们就可以定义多个profile,然后每个profile对应不同的激活条件和配置信息,从而达到不同环境使用不同 ...
- CAS (13) —— CAS 使用Maven Profile支持多环境编译
CAS (13) -- CAS 使用Maven Profile支持多环境编译 摘要 CAS 使用Maven Profile支持多环境编译 版本 tomcat版本: tomcat-8.0.29 jdk版 ...
- maven profile 优先级
maven profile是有优先级别 也就是说在setting.xml的profile优先级比pom中同名的profile高. 可以使用 mvn help:active-profiles 这个命令是 ...
- How to activate maven profile inside eclipse
How to activate maven profile inside eclipse Normally maven is use for project dependency management ...
- 记录一次诡异的Maven Profile不生效的问题
记录一次诡异的Maven Profile不生效的问题 现象 maven 打包之后,复制的 profile对应的resource文件总是不正确的. 即便是加了 mvn clean package -P ...
随机推荐
- js简单对象List自定义属性排序
简单对象List自定义属性排序 <script type="text/javascript"> var objectList = new Array(); functi ...
- RequestMapping原理分析和RequestMappingHandlerMapping
转载https://juejin.im/post/5cbeadb96fb9a031ff0d18b5 源码版本spring-webmvc-4.3.7.RELEASE 使用Spring MVC的同学一般都 ...
- AppBoxFuture: 大数据表分区的3种策略
之前的文章"分而治之"在介绍大表分区时,作者尚未实现不同的分区策略,即只能按指定的分区键进行分区.这次作者完善了一下分区策略,在规划大表分区时可以按Hash或者时间范围进行分区 ...
- 关于AI本质的思考
前言 最近几天和一位朋友探讨了一下现阶段的人工智能以及未来发展,并且仔细重读了尤瓦尔赫拉利的“简史三部曲”,产生了一些关于AI的新想法,觉得有必要整理出来. 程序.AI的本质 现代的计算机都是基于图灵 ...
- php抽奖概率程序
抽奖概率思想: 1.给每一个奖项设置要给概率数,如下面所有奖品综合设置为100,iphone5s是5,也就是5% 2.然后通过php生成随机数函数生成一个在总概率之间的随机数 如:抽第一个奖品5s的时 ...
- Frameset下的frame动态隐藏
技术涉及:html+Jquery 不多说直接上图:由于是 .netcore MVC Web应用对于大家来说不一致的话可供参考哦
- Python之matplotlib库学习:实现数据可视化
1. 安装和文档 pip install matplotlib 官方文档 为了方便显示图像,还使用了ipython qtconsole方便显示.具体怎么弄网上搜一下就很多教程了. pyplot模块是提 ...
- MySQL sys Schema 简单介绍-2
之前在<MySQL sys Schema 简单介绍-1>中简单的介绍了,sys Schema库中的表.那么这些表都可以查询些什么信息呢?接下来本文将做下介绍. 1. 表的情况 1.1 统计 ...
- 9.22考试 crf的军训 题解
做这道题时由于第一道题太水了,第一反应是NOIP T2级别的题,需要拿上70~100的分,然后就开始分析,当然最后事实证明我错了…… 这道题当时首先联想到了 NOIP2016愤怒的小鸟 当然,数据范围 ...
- 星际旅行(欧拉路,欧拉回路)(20190718 NOIP模拟测试5)
瞎搞了一个ans+=du*(du-1)/2 wa20分,好桑心(话外音:居然还有二十分,出题人太周到了) 还是判欧拉路 题解没太仔细想,感觉还是kx的思路明白 具体就是:因为每条边要走两遍,可以把一条 ...