现象和问题:
写了个 xx-service 的基于maven项目,借助spring配置文件可执行,现在有需求是希望将该项目以SDk方式打包到maven仓库以便使用其中某些service类(暂不论合理与否),如何通过maven profile实现在编辑器里不同开发人员默认用不同的 active profile?
实现不同的 active profile是希望双方在开发的时候,一个可以直接package出来 不含配置文件的纯 SDK 包,而我这边使用eclipse时可以默认生成需要的配置文件(local profile)到classpath下,免于命令行切换,提高开发/测试效率。
源项目通过Main函数启动,所以一种方案是定义spring.active.profile的方式,在eclipse配置参数方式启动,但是我不希望引入这种不纯粹的方式,过多依赖在一些零散的地方设置,就像我觉得使用lomb组件的不配谈代码优雅。
大部分了解maven的会想到active profile实现,但我也不想通过maven安装包下的 settings.xml中使用activeProfiles指定的方式,更不想通过两人部分代码不同的方式实现,即希望两人看到的代码一样。
最好能都在项目代码里如pom.xml/xx.properties(配置即是代码!)里设置搞定。
那么有什么好办法呢?
因为classpath生成是在编译之后,即maven编译之后的,所以不要妄想通过eclipse的配置 jvm run 参数,必定是在maven编译前或时(eclipse通过m2e和maven交互即时编译),而maven pom.xml没有支持 if-else这类表达式语言的,实际上maevn基于配置的理念并不能支持其如DSL一般灵活,gradle可以。m2eclipse只是扩展了maven集成到eclipse的能力,并未扩展功能。
如果pom指定了A profile为active的,没有理由在其他人机器上A profile不是active的,除非maven支持基于机器等设置profile。好在maven 对profile本身支持力度是勉强可以达到上述功能。
让我们先看看官方支持激活profile的几种方式:
|
|
所以解决办法就是环境变量或者文件是否存在的方式。
该方式虽然也依赖一些配置,但好处是一目了然,看到代码即可明白。
通过上述配置,在我的eclipse上是classpath下包含配置的local模式可运行项目,而在对方机器就是sdk可打包项目,非常轻便了。
对方可通过 mvn deploy 正常的发布包,但是,当我使用 “mvn package deploy -Psdk” 时,却发现打出来的包中包含了配置文件!
为什么,指定了 sdk 的profile却发现配置文件被包含进来
怎么定位问题呢?使用 help:active-profiles 命令试试:
即,”mvn -P sdk”并不表示 仅使用 sdk 或parent/setting.xml里指定的active的profile打包,还包括任何能够匹配的profile!
即上面输出里看到的,默认生效的profile有 settings.xml定义的 sonar/gdev,还有本pom.xml里的 local/sdk 的profile,以及父类的默认 dev ,这是一个注意事项
怎么解决或者原因在哪呢?
其实 -P 参数支持简单的包含/排除运算,即 mvn package deploy -Plocal 就表示排除 local 这个active profile, !local 也表示排除, +local表示添加 local,这是一个技巧,代码:
这是第二个技巧
但为什么 sonar/gdev/local/sdk/dev 这些profile都生效了?
在
org.apache.maven.cli.configuration.SettingsXmlConfigurationProcessor.populateFromSettings(MavenExecutionRequest, Settings)
这个方法有涉及,不过这里我们倒序追溯一下:
mvn 命令的入口都在 org.apache.maven.cli.MavenCli 类里面,MavenCli 封装配置build好一个MavenExecutionRequest 之后,最终调用DefaultMaven.doExecute(MavenExecutionRequest request)实现,也是所有maven项目的MavenExecutionRequest,Project/Module/Artifact等都是在此实现的,该方法会调用这个方法进行 Project 的初始化:
org.apache.maven.project.DefaultProjectBuilder.initProject(MavenProject, ModelBuildingResult, Map
这几个方法就是分别从 pom/父项目/maven settings中获取active profile的,而profile 判定isActive是支持系统变量方式的:
三类profile都会作为maven project的Active Profiles,这也是 help:active-profiles 实现原理。
其他
说两个不相关的问题:
1.
Mac 的sed命令不支持一些linux sed写法 众所周知,有时甚至导致一些莫名其妙运行结果,故建议避免使用,改为linux sed 即安装gsed:
brew install gnu-sed
不过不建议把gsed替换或直接别名为sed, 有些外部进程会调用sed。
2.
最近在写一个Chrome extension,发现下面写法返回空,要是把 sendResponse 放到chrome.storage.local.get的回调函数里就会报一个 类似:
“unchecked runtime lasterror the message port closed before a response”的错误,原因就是因为异步且没有作为回调函数的方式,但即便用Promise也是该情况,
解决办法是给函数加一个简单的 return true;即把下面else里已有的注释掉,现有注释部分打开,就解决该问题了。https://github.com/mozilla/webextension-polyfill/issues/130
虽然写过一些js代码,但觉得js的这个功能很神奇。