maven打包多环境,这个问题在百度上一搜遍地都是,一般答案都是mvn clean package -DskipTests -Pdev
、mvn clean package -DskipTests -Ptest
、mvn clean package -DskipTests -Pprod
等。
那么,有点人(如我)有问,maven是怎么实现的呢。带着这个问题,我写了一个小项目来模拟基本的实现方案,项目名为resource-filter(比较low),代码见https://gitee.com/valuetodays/mvn-all/tree/master/resource-filter。
我们要实现的是,如何把一个文件中的${}里的内容替换成具体的值
,这个问题可以简化一下,我们如何把一个字符串中的${}里的内容替换成具体的值
。
上面这两种情况,我们只要实现了后者,前者就不难解决了。
处理字符串
想解决问题的话,我们就模拟一个问题,假设有一个字符串的内容为this file is by ${name}\n\n -- on ${date}
,另有一个Map里含有name和date对应的value值,如何写一个程序将原字符串转换成新字符串。约定变量名如下:
final String input = "this file is by ${name}\n\n -- on ${date}";
final String name = "billy"
final String date = "2018-06-06"
当然,该程序有个简单的实现使用字符串的替换方法 把name和date都替换就行了,即
String output = input.replace("${name}", name).replace("${date}", date);
诚然可以解决我们的问题,但我们考虑的是处理一种框架的行为,或者说,我们要重复造个轮子。
基于上述情况,我们可以新建如下类:
- 一个ResourceFilter(存放key-value)
- 一个Resouce(抽象类或接口)
- 一个StringResource(处理字符串的程序)
- 一个FileResource(处理文件的程序)
简单说一下ResourceFilter这个类,它其实是Map的一种封装,里面有一个Map<String, String>
,这个类有点像Spring的StandardEnvironment类,需要说明的是,ResourceFilter拥有一个Map,而不是一个Map。
而替换${}的操作,则可以从开源框架中copy的(嘘,这是借鉴),我所了解的有两类实现,一类是Mybatis的,一类是Spring的。我先使用Spring的,因为好久没有看过Mybatis了。Spring的相关实现代码在org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#parseStringValue
中,我使用的是Spring-V1.2.1的版本(该版本的代码我已整理出来供自己研究,在https://gitee.com/valuetodays/spring-V1.2.1-src/blob/master/src/main/java/org/springframework/beans/factory/config/PropertyPlaceholderConfigurer.java中),其实spring的代码是很严谨的,它的好多类的好多方法都是protected的,在外面无法访问,好了,不多说了。
如此一来,我们的StringResource初具雏形。其伪代码如下
public class StringResource {
public String doFilter(String input, ResourceFilter resourceFilter) {
// 使用Spring的处理${}的方法
}
}
完成后,我们会着手编写FileResource这个类,这个类的处理方式和StringResource类似,不过它是从文件中读取字符串,处理完后,再写入到另一个文件中。对!还得处理字符串,我们显然不会把StringResource里面的代码copy一份使用,这里我们有两种方案:
- 方案一:让FileResource调用StringResource
- 方案二:提取出StringResource类中的字符串操作方法成一个工具类
我采取的是方案二,方案一是我在写该博客时想到的。发现方案二更合理。因为FileResource和StringResource是同等的并列关系而不是所属关系。
添加 PlaceHolderParser
我们可以添加一个PlaceHolderParser,让它来做具体的处理工作。注意它是一个接口或抽象类,现在有一个实现类名叫SpringPlaceHolderParser的子类,不错,后期,还可以添加一个名称MybatisPlaceHolderParser的子类~~ 接着就可以把原来StringResource的doFilter方法的内容移到SpringPlaceHolderParser中。大致代码见https://gitee.com/valuetodays/mvn-all/tree/master/resource-filter