最近博主开发了一个用于接收数据的接口服务器,一开始数据是外部购买的,数据源只有一个地方,但是随着业务的拓展,公司不打算全部数据都从外部购买,而是将其中一部分数据交给公司爬虫部门来爬取,这样数据源变成了两处。但是博主的接口服务器还有一个监控模块,主要是用来实时展示数据进来的详情,正是由于监控模块的存在,对应不同的数据源博主还得改源码来满足不同的需求,这样一来就很坑了,如果每次新增个数据源我都要做个自定义的那得多麻烦,于是乎博主在分析整个架构后,将代码做了重构,最后重构的情况就是生成一个常量类,每次争对不同的数据源,将常量类里面对应的常量注释掉即可。这下操作起来就方便多了,每次来个新的数据源,博主只需要新增常量并将其它的常量注释掉即可。由于前面都是开发阶段,博主想怎么整都可以,但是后面进入了流程化阶段了,项目需要交给配置管理组管理,打包发布什么的都是由配置管理组来负责,但是前面博主说了,对不同数据源博主需要注释常量类里面的一些字段来打包,但是项目交给配管组后,配管组是没权限该代码了,这就很尴尬了,博主的小聪明在这里就行不通了。于是乎,博主又开始耍小聪明了,能不能让配置组打包的时候加个参数什么的来实现对常量类的修改,博主找遍了整个互联网都没找到这样的插件(或者说操作简单,兼容性好的插件),所以博主打算自己开发一个maven插件。
通过mvn指令传递参数来实现打包前修改项目源码。
IDEA新建一个maven项目,注意选择maven-archetype-mojo这个模板
没错,就是这么简单,只要两步,因为你在选择好模板创建项目后,idea已经自动加入了一些依赖,并生成一个mojo类,该类继承自AbstractMojo。该类里面有一个execute方法,execute是程序的主入口。
有两种方式声明一个类是mojo类,一种是通过文档注解的方式,如下所示:
/**
* @goal ChangeConstant
*/
另外一种是通过添加@Mojo(name = “ChangeConstant”)注解的方式来声明,注解方式需要加依赖:
org.apache.maven.plugin-tools
maven-plugin-annotations
3.4
goal的作用后面会说明
在使用maven插件的时候,有时需要传递一些参数,参数功能可以通过文档注释或者注解来声明。比如我要传递一个文件路径的参数,这里使用注解来声明:
@Parameter( property = "ChangeConstant.filePath", defaultValue = "filePath default" )
private String filePath;
这里博主希望在打包前对常量类做修改,常量类如下,如果是内部源,则将对外监控那四个常量注释掉,如果是对外监控,则将内部监控那四个常量注释掉。
//对外监控
// public static final String logrecord = "logrecord";
// public static final String usrbyzqsjyb = "usrbyzqsjyb";
// public static final String usrbyzxsltj = "usrbyzxsltj";
// public static final String usrbyzxxq = "usrbyzxxq";
//内部监控
public static final String logrecord = "logrecord_inner";
public static final String usrbyzqsjyb = "usrbyzqsjyb_inner";
public static final String usrbyzxsltj = "usrbyzxsltj_inner";
public static final String usrbyzxxq = "usrbyzxxq_inner";
修改文件就不详叙了,大体思路就是读进来->修改->写入。下面是博主的插件类源码:
package com.riclee;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import java.io.*;
/**
* author: lichao
* date: 2019/04/08
*/
@Mojo(name = "ChangeConstant")
public class ChangeConstantMojo extends AbstractMojo
{
@Parameter( property = "ChangeConstant.project", defaultValue = "${project}" )
private MavenProject project;
@Parameter( property = "ChangeConstant.filePath", defaultValue = "filePath default" )
private String filePath;
@Parameter( property = "ChangeConstant.type", defaultValue = "bydata" )
private String type;
public void execute()
throws MojoExecutionException
{
filePath = project.getBasedir() + filePath;
//根据操作系统类型,修改目录分隔符
if(File.separator.equals("/")){
filePath = filePath.replaceAll("\\\\","/");
}else if(File.separator.equals("\\")){
filePath = filePath.replaceAll("[/]","\\\\");
}
getLog().info("filePath = " + filePath);
if(type.equals("bydata")){
getLog().info("type = " + type + ", 对外接口服务" );
}else if(type.equals("innerdata")){
getLog().info("type = " + type + ", 内部采集接口服务" );
}
try{
FileReader fr = new FileReader(filePath);
BufferedReader bfr = new BufferedReader(fr);
String line = null;
StringBuffer newContent = new StringBuffer();
while((line = bfr.readLine())!=null){
if(type.equals("bydata")){
if(line.contains("logrecord")){
lineChange(line,newContent);
}else if(line.contains("usrbyzqsjyb")){
lineChange(line,newContent);
}else if(line.contains("usrbyzxsltj")){
lineChange(line,newContent);
}else if(line.contains("usrbyzxxq")){
lineChange(line,newContent);
}else{
newContent.append(line + System.lineSeparator());
}
}
if(type.equals("innerdata")){
if(line.contains("logrecord")){
lineChange2(line,newContent);
}else if(line.contains("usrbyzqsjyb")){
lineChange2(line,newContent);
}else if(line.contains("usrbyzxsltj")){
lineChange2(line,newContent);
}else if(line.contains("usrbyzxxq")){
lineChange2(line,newContent);
}else{
newContent.append(line + System.lineSeparator());
}
}
}
fr.close();
bfr.close();
BufferedWriter bfw = new BufferedWriter(new FileWriter(filePath));
bfw.write(newContent.toString());
bfw.close();
}catch (IOException e){
e.printStackTrace();
}
}
public void lineChange(String line,StringBuffer sb){
if(line.contains("inner")){
if(!line.contains("//")){
sb.append("//" + line + System.lineSeparator());
}else{
sb.append(line + System.lineSeparator());
}
}else{
sb.append(line.replaceAll("//","") + System.lineSeparator());
}
}
public void lineChange2(String line,StringBuffer sb){
if(line.contains("inner")){
sb.append(line.replaceAll("//","") + System.lineSeparator());
}else{
if(!line.contains("//")){
sb.append("//" + line + System.lineSeparator());
}else{
sb.append(line + System.lineSeparator());
}
}
}
}
Pom依赖
4.0.0
com.riclee
change-constant-maven-plugin
maven-plugin
1.0.0
org.apache.maven.plugins
maven-compiler-plugin
1.7
change-constant-maven-plugin Maven Mojo
http://maven.apache.org
org.apache.maven
maven-plugin-api
2.0
org.apache.maven.plugin-tools
maven-plugin-annotations
3.4
org.apache.maven
maven-project
2.2.1
插件开发好后install一下,提交到仓库中,根据你所配置的坐标地址,在项目中引用
com.gildata
change-constant-maven-plugin
1.0.1
ChangeConstant
pre-clean
ChangeConstant
其中phase是指定你要在哪个生命周期使用插件,goal就是@mojo注解中的值。
前面在开发插件的时候添加过一些参数,这些参数也可以在pom文件中指定默认值。
dev
\src\main\java\com\gildata\byinterserver\constant\Constant.java
bydata
在打包的时候可以动态指定参数的值来覆盖默认值
mvn -DChangeConstant.type=innerdata clean package
以上只是博主的抛砖引玉,maven插件更详细的使用可以参考文档:
https://maven.apache.org/guides/introduction/introduction-to-plugins.html