使用maven插件修改jar包中的class并推送源码

老铁们好,我是V,今天我们简单聊聊怎么修改jar包中的类

背景

我们有时候需要修改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
在这里插入图片描述

对应的插件设置也很简单

 <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 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 但是没有源码

于是我们添加

 <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文件夹

     <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目录
     <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 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

mvn clean source:jar compile

我看下打包好的sources jar

在这里插入图片描述

舒服了

推送源码

但是问题又来了

这样本来一个项目被我们分成了两个,这时候推送分两次使用mvn clean deploy -DskipTests推送jar包,特别是snapshot的jar会有maven-metadata.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到本地
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的后缀

```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/ 
```

结语

收工搞定,虽然这个方法还是不够优雅,但是好歹也不是太高频的操作,解决了打包源码的问题凑合用得了。

如果大佬们有更好的方法,请在评论区教教我,嘿嘿。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值