使用Maven Shade插件可以将所有的依赖包、类库和所需的资源打包到一个可执行的Jar文件中,从而避免在运行时出现项目版本冲突的问题。以下是使用Maven Shade插件解决项目版本冲突的完整攻略:
环境要求
- JDK 1.8+
- Maven 3.x+
使用Maven Shade插件
在pom.xml文件中添加以下配置:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<!-- 打包后的Jar文件名称 -->
<finalName>my-app</finalName>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.example.MainClass</mainClass>
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<id>shade-my-app</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
上述配置中,配置了打包后的Jar文件名称<finalName>
、剔除了Jar文件中的签名文件<filters>
,以及设置Jar文件的MANIFEST.MF中的mainClass<transformers>
。同时,在项目的打包阶段,执行maven-shade-plugin插件的shade目标<executions>
。
例子
假设有一个Spring Boot应用程序,它依赖于Spring的4.1.9版本和Logback的1.2.3版本。为了避免运行时出现版本冲突的问题,可以使用Maven Shade插件将所有所需的依赖包打包到一个可执行的Jar文件中。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
使用以上依赖后,在打包后运行应用程序时可能会出现版本冲突的问题。如果不使用Maven Shade插件会出现以下错误信息:
Exception in thread "main" java.lang.NoSuchMethodError: org.springframework.core.ResolvableType.forInstance(Ljava/lang/Object;)Lorg/springframework/core/ResolvableType;
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:471)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:249)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:155)
为了避免这个问题,可以使用Maven Shade插件将所有所需的依赖包和类库打包到一个可执行的Jar文件中。修改pom.xml文件,添加以下配置:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<finalName>my-app</finalName>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.example.MainClass</mainClass>
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<id>shade-my-app</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
然后运行以下命令进行打包:
mvn clean package
此时,Maven Shade插件会将依赖包打包到一个名为my-app-1.0-SNAPSHOT.jar的可执行文件中。
另外一个例子是,有一个新的项目依赖于mysqldump和mysql-connector-java,其中mysqldump是一个命令行程序,它可以将MySQL数据库中的内容备份到文件中。mysql-connector-java是一个MySQL的JDBC驱动程序,它是Java应用程序连接MySQL的必备组件。因为mysqldump是一个命令行程序,它不可能成为Java应用程序的依赖项。因此,可以使用Maven Shade插件将mysqldump打包到Java应用程序中。
假设mysqldump的可执行文件位于$PATH中。修改pom.xml文件,添加以下配置:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<finalName>my-app</finalName>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.example.MainClass</mainClass>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/maven/groupId/artifactId/dependency-reduced-pom.xml</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
<resource>mysqldump</resource>
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<id>shade-my-app</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
此时,运行以下命令进行打包:
mvn clean package
Maven Shade插件将mysqldump打包到my-app-1.0-SNAPSHOT.jar文件中。在运行应用程序时,可以从my-app.jar文件解压mysqldump,然后调用它来备份MySQL数据库:
$ mkdir -p tmp/mysql
$ java -jar my-app.jar mysqldump -hlocalhost -uroot -p --all-databases > tmp/mysql/all-databases.sql
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:使用maven shade插件解决项目版本冲突详解 - Python技术站