場景描述
最近博主開發了一個用於接收數據的接口服務器,一開始數據是外部購買的,數據源只有一個地方,但是隨着業務的拓展,公司不打算全部數據都從外部購買,而是將其中一部分數據交給公司爬蟲部門來爬取,這樣數據源變成了兩處。但是博主的接口服務器還有一個監控模塊,主要是用來實時展示數據進來的詳情,正是由於監控模塊的存在,對應不同的數據源博主還得改源碼來滿足不同的需求,這樣一來就很坑了,如果每次新增個數據源我都要做個自定義的那得多麻煩,於是乎博主在分析整個架構後,將代碼做了重構,最後重構的情況就是生成一個常量類,每次爭對不同的數據源,將常量類裏面對應的常量註釋掉即可。這下操作起來就方便多了,每次來個新的數據源,博主只需要新增常量並將其它的常量註釋掉即可。由於前面都是開發階段,博主想怎麼整都可以,但是後面進入了流程化階段了,項目需要交給配置管理組管理,打包發佈什麼的都是由配置管理組來負責,但是前面博主說了,對不同數據源博主需要註釋常量類裏面的一些字段來打包,但是項目交給配管組後,配管組是沒權限該代碼了,這就很尷尬了,博主的小聰明在這裏就行不通了。於是乎,博主又開始耍小聰明瞭,能不能讓配置組打包的時候加個參數什麼的來實現對常量類的修改,博主找遍了整個互聯網都沒找到這樣的插件(或者說操作簡單,兼容性好的插件),所以博主打算自己開發一個maven插件。
插件功能
通過mvn指令傳遞參數來實現打包前修改項目源碼。
插件開發
第一步:創建插件項目
IDEA新建一個maven項目,注意選擇maven-archetype-mojo這個模板
第二步:插件實現
沒錯,就是這麼簡單,只要兩步,因爲你在選擇好模板創建項目後,idea已經自動加入了一些依賴,並生成一個mojo類,該類繼承自AbstractMojo。該類裏面有一個execute方法,execute是程序的主入口。
2.1 聲明mojo類(插件)
有兩種方式聲明一個類是mojo類,一種是通過文檔註解的方式,如下所示:
/**
* @goal ChangeConstant
*/
另外一種是通過添加@Mojo(name = “ChangeConstant”)註解的方式來聲明,註解方式需要加依賴:
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.4</version>
</dependency>
goal的作用後面會說明
2.2 添加參數
在使用maven插件的時候,有時需要傳遞一些參數,參數功能可以通過文檔註釋或者註解來聲明。比如我要傳遞一個文件路徑的參數,這裏使用註解來聲明:
@Parameter( property = "ChangeConstant.filePath", defaultValue = "filePath default" )
private String filePath;
2.3 execut方法實現自定義插件功能
這裏博主希望在打包前對常量類做修改,常量類如下,如果是內部源,則將對外監控那四個常量註釋掉,如果是對外監控,則將內部監控那四個常量註釋掉。
//對外監控
// 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依賴
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.riclee</groupId>
<artifactId>change-constant-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<version>1.0.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<name>change-constant-maven-plugin Maven Mojo</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>2.2.1</version>
</dependency>
</dependencies>
</project>
2.4插件使用
插件開發好後install一下,提交到倉庫中,根據你所配置的座標地址,在項目中引用
<plugins>
<plugin>
<groupId>com.gildata</groupId>
<artifactId>change-constant-maven-plugin</artifactId>
<version>1.0.1</version>
<executions>
<execution>
<id>ChangeConstant</id>
<phase>pre-clean</phase>
<goals>
<goal>ChangeConstant</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
其中phase是指定你要在哪個生命週期使用插件,goal就是@mojo註解中的值。
前面在開發插件的時候添加過一些參數,這些參數也可以在pom文件中指定默認值。
<properties>
<spring.profiles.active>dev</spring.profiles.active>
<ChangeConstant.filePath>\src\main\java\com\gildata\byinterserver\constant\Constant.java</ChangeConstant.filePath>
<ChangeConstant.type>bydata</ChangeConstant.type>
</properties>
在打包的時候可以動態指定參數的值來覆蓋默認值
mvn -DChangeConstant.type=innerdata clean package
以上只是博主的拋磚引玉,maven插件更詳細的使用可以參考文檔:
https://maven.apache.org/guides/introduction/introduction-to-plugins.html