背景
我们有时候需要修改jar中的某个class,有时候是因为需要修复某些bug,有时候是定制化开发
例如为了实现es的索引动态修改索引中的压缩算法,我们需要修改lucene-core中的IndexWriter.class这个类
解决方案
方法一、解压jar包将修改后的class放进去重新压缩
这个方法虽然可行,但是显得很蠢
方法二、下载源码自己编译修改
从github上下载源码后,自己修改源码,重新编译,这当然是最彻底的解决方案。但是lucene-core 7.7.3是用ant编译的,是我太菜了,我试了很多次,都没编译成功。
方法三、maven-dependency-plugin插件替换class打包
这也是本文重点介绍的方法
我们建好java项目后,将IndexWriter.java源码复制出来,放到指定的package修改好后放到指定的package
对应的插件设置也很简单
xml
代码解读
复制代码
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>${maven-dependency-plugin.version}</version> <executions> <execution> <id>replace-custom-class</id> <phase>generate-sources</phase> <goals> <goal>unpack</goal> </goals> <configuration> <artifactItems> <artifactItem> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <overWrite>false</overWrite> <outputDirectory>${project.build.directory}/classes</outputDirectory> </artifactItem> </artifactItems> </configuration> </execution> </executions> </plugin>
这样插件就会将lucene-core的class解压,然后将我们自定义的IndexWriter编译后覆盖原生的IndexWriter.class
完整pom.xml
xml
代码解读
复制代码
<?xml version="1.0" encoding="UTF-8"?> <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <version>${lucene-core.version}-0.0.1-SNAPSHOT</version> <properties> <java.version>8</java.version> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version> <maven-compiler-plugin.encoding>UTF-8</maven-compiler-plugin.encoding> <maven-dependency-plugin.version>3.6.0</maven-dependency-plugin.version> <maven-source-plugin.version>3.3.0</maven-source-plugin.version> <lucene-core.version>7.7.3</lucene-core.version> </properties> <dependencies> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <version>${lucene-core.version}</version> </dependency> </dependencies> <distributionManagement> <snapshotRepository> <id>xxx-snapshots</id> <name>Nexus Snapshot Repository</name> <url>http://xxx.com/nexus/content/repositories/snapshots/</url> </snapshotRepository> <repository> <id>xxx-releases</id> <name>Nexus Release Repository</name> <url>http://xxx.com/nexus/content/repositories/releases/</url> </repository> </distributionManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${maven-compiler-plugin.version}</version> <configuration> <source>${java.version}</source> <target>${java.version}</target> <encoding>${maven-compiler-plugin.encoding}</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>${maven-dependency-plugin.version}</version> <executions> <execution> <id>replace-custom-class</id> <phase>generate-sources</phase> <goals> <goal>unpack</goal> </goals> <configuration> <artifactItems> <artifactItem> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <overWrite>false</overWrite> <outputDirectory>${project.build.directory}/classes</outputDirectory> </artifactItem> </artifactItems> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
执行命令打包
代码解读
复制代码
mvn clean install -DskipTests
这样得到的jar就可以直接用了
遇到的问题
你以为这就结束了吗?虽然我们功能实现了,但是jar包中的其他的类的源码无法查看了,虽然不影响使用,但是有些膈应。
源码无法查看
虽然通过上面的方式我们得到了定制化的jar lucene-core-7.7.3-0.0.1-SNAPSHOT.jar 但是没有源码
于是我们添加
xml
代码解读
复制代码
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <version>3.2.1</version> <executions> <execution> <id>attach-sources</id> <phase>package</phase> <goals> <goal>jar</goal> </goals> <configuration> <attach>true</attach> </configuration> </execution> </executions> </plugin>
我们看看下源码
麻了,这里面只有我们修改的类的源码,虽然不影响使用,但是后续我们debug的时候会非常麻。
查了很久的资料,发现maven-source-plugin没有办法指定源码的位置,于是就采用了另外一个不太优雅的方法
打包源码
首先我们在目录下另外建一个lucene-core-7.7.3-sources
里面不需要任何内容
方案
-
generate-sources阶段使用maven-dependency-plugin解压lucene-core-sources.jar到lucene-core-7.7.3-sources/src/main/java文件夹
xml
代码解读
复制代码
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>${maven-dependency-plugin.version}</version> <executions> <execution> <id>source-unpack</id> <phase>generate-sources</phase> <goals> <goal>unpack</goal> </goals> <configuration> <artifactItems> <artifactItem> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <overWrite>false</overWrite> <classifier>sources</classifier> <outputDirectory>${project.basedir}/src/main/java</outputDirectory> </artifactItem> </artifactItems> </configuration> </execution> </executions> </plugin>
-
使用exec-maven-plugin拷贝lucene-core-7.7.3中的源码到lucene-core-7.7.3-sources/src/main/java目录下
这个插件主要作用
- clean阶段清理lucene-core-7.7.3-sources/src/main文件夹
- generate-sources阶段拷贝lucene-core-7.7.3/src/main/java/org/apache/lucene/index/IndexWriter.java到lucene-core-7.7.3-sources对应目录
- compile阶段清理lucene-core-7.7.3-sources/src/main/java目录
这边整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记的【点击此处即可】免费获取
xml
代码解读
复制代码
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.2.0</version> <executions> <!-- source.jar生成之前,clean阶段清理main/java文件夹 --> <execution> <id>clean-sources</id> <phase>clean</phase> <goals> <goal>exec</goal> </goals> <configuration> <executable>bash</executable> <arguments> <argument>-c</argument> <argument>rm -rf ${project.basedir}/src/main/</argument> </arguments> </configuration> </execution> <!-- 从lucene-core-7.7.3中拷贝源码到main/java文件夹 --> <execution> <id>copy-custom-sources</id> <phase>generate-sources</phase> <goals> <goal>exec</goal> </goals> <configuration> <executable>bash</executable> <arguments> <argument>-c</argument> <argument>cp -r ${project.basedir}/../lucene-core-${lucene-core.version}/src/main/java ${project.basedir}/src/main/</argument> </arguments> </configuration> </execution> <!-- compile阶段清理main/java文件夹 --> <execution> <id>clean-sources-after-compile</id> <phase>compile</phase> <goals> <goal>exec</goal> </goals> <configuration> <executable>bash</executable> <arguments> <argument>-c</argument> <argument>rm -rf ${project.basedir}/src/main/</argument> </arguments> </configuration> </execution> </executions> </plugin>
-
使用maven-source-plugin打包源码
这个大家都熟悉,就懒得贴了
完整pom.xml如下
xml
代码解读
复制代码
<?xml version="1.0" encoding="UTF-8"?> <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <version>${lucene-core.version}-0.0.1-SNAPSHOT</version> <properties> <java.version>8</java.version> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version> <maven-compiler-plugin.encoding>UTF-8</maven-compiler-plugin.encoding> <maven-dependency-plugin.version>3.6.0</maven-dependency-plugin.version> <maven-source-plugin.version>3.3.0</maven-source-plugin.version> <lucene-core.version>7.7.3</lucene-core.version> </properties> <dependencies> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <version>${lucene-core.version}</version> </dependency> </dependencies> <distributionManagement> <snapshotRepository> <id>xxx-snapshots</id> <name>Nexus Snapshot Repository</name> <url>http://xxx.com/nexus/content/repositories/snapshots/</url> </snapshotRepository> <repository> <id>xxx-releases</id> <name>Nexus Release Repository</name> <url>http://xxx.com/nexus/content/repositories/releases/</url> </repository> </distributionManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${maven-compiler-plugin.version}</version> <configuration> <skip>true</skip> <source>${java.version}</source> <target>${java.version}</target> <encoding>${maven-compiler-plugin.encoding}</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <version>3.2.1</version> <executions> <execution> <id>attach-sources</id> <phase>package</phase> <goals> <goal>jar</goal> </goals> <configuration> <attach>true</attach> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>${maven-dependency-plugin.version}</version> <executions> <execution> <id>source-unpack</id> <phase>generate-sources</phase> <goals> <goal>unpack</goal> </goals> <configuration> <artifactItems> <artifactItem> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <overWrite>false</overWrite> <classifier>sources</classifier> <outputDirectory>${project.basedir}/src/main/java</outputDirectory> </artifactItem> </artifactItems> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.2.0</version> <executions> <!-- source.jar生成之前,clean阶段清理main/java文件夹 --> <execution> <id>clean-sources</id> <phase>clean</phase> <goals> <goal>exec</goal> </goals> <configuration> <executable>bash</executable> <arguments> <argument>-c</argument> <argument>rm -rf ${project.basedir}/src/main/</argument> </arguments> </configuration> </execution> <!-- 从lucene-core-7.7.3中拷贝源码到main/java文件夹 --> <execution> <id>copy-custom-sources</id> <phase>generate-sources</phase> <goals> <goal>exec</goal> </goals> <configuration> <executable>bash</executable> <arguments> <argument>-c</argument> <argument>cp -r ${project.basedir}/../lucene-core-${lucene-core.version}/src/main/java ${project.basedir}/src/main/</argument> </arguments> </configuration> </execution> <!-- source.jar生成完毕,compile阶段清理main/java文件夹 --> <execution> <id>clean-sources-after-compile</id> <phase>compile</phase> <goals> <goal>exec</goal> </goals> <configuration> <executable>bash</executable> <arguments> <argument>-c</argument> <argument>rm -rf ${project.basedir}/src/main/</argument> </arguments> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
执行命令打包source.jar
这里的compile是为了触发clean-sources-after-compile
bash
代码解读
复制代码
mvn clean source:jar compile
我看下打包好的sources jar
舒服了
推送源码
但是问题又来了
这样本来一个项目被我们分成了两个,这时候推送分两次使用mvn clean deploy -DskipTests
推送jar包,特别是snapshot的jar会有maven-metadata.xml
xml
代码解读
复制代码
<metadata modelVersion="1.1.0"> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <version>7.7.3-0.0.1-SNAPSHOT</version> <versioning> <snapshot> <timestamp>20240811.061414</timestamp> <buildNumber>17</buildNumber> </snapshot> <lastUpdated>20240811061414</lastUpdated> <snapshotVersions> <snapshotVersion> <extension>jar</extension> <value>7.7.3-0.0.1-20240811.061414-17</value> <updated>20240811061414</updated> </snapshotVersion> <snapshotVersion> <extension>pom</extension> <value>7.7.3-0.0.1-20240811.061414-17</value> <updated>20240811061414</updated> </snapshotVersion> <snapshotVersion> <classifier>sources</classifier> <extension>jar</extension> <value>7.7.3-0.0.1-20240811.061532-17</value> <updated>20240811061532</updated> </snapshotVersion> </snapshotVersions> </versioning> </metadata>
我们会发现jar的版本和sources jar的版本不一致,导致在idea中无法匹配
所以需要一次性将jar和sources jar一起推送到maven仓库才行
经过一番查阅资料后发现可以用mvn命令可以解决问题
安装sources jar到本地
ini
代码解读
复制代码
mvn install:install-file \ -Dfile=$PWD/lucene-core-7.7.3-sources/target/lucene-core-7.7.3-0.0.1-SNAPSHOT-sources.jar \ -DgroupId=org.apache.lucene \ -DartifactId=lucene-core \ -Dversion=7.7.3-0.0.1-SNAPSHOT \ -Dpackaging=jar \ -Dclassifier=sources
同时推送jar和source.jar
好了,注意看,这行命令就是这篇文章最有价值的地方了
使用-Dfile指定jar的路径
使用-Dfiles指定source jar的路径,使用-Dtypes指定source jar的后缀
ini
代码解读
复制代码
```bash mvn deploy:deploy-file \ -DgroupId=org.apache.lucene \ -DartifactId=lucene-core \ -Dversion=7.7.3-0.0.1-SNAPSHOT \ -Dpackaging=jar \ -Dfile=$PWD/lucene-core-7.7.3/target/lucene-core-7.7.3-0.0.1-SNAPSHOT.jar \ -Dclassifiers=sources \ -Dtypes=jar \ -Dfiles=$PWD/lucene-core-7.7.3-sources/target/lucene-core-7.7.3-0.0.1-SNAPSHOT-sources.jar \ -DrepositoryId=xxx-snapshots \ -Durl=http://xxx.com/nexus/content/repositories/snapshots/ ```
结语
收工搞定,虽然这个方法还是不够优雅,但是好歹也不是太高频的操作,解决了打包源码的问题凑合用得了。