微服务的热潮,慢慢讲jar引入了码农的视线之中,从传统web开发中过来的人面对这个东西也算是个新鲜事了,接下来聊一聊在maven下生成可运行jar的那些事。
Maven可以使用mvn package
指令对项目进行打包生成jar文件,如果直接使用java -jar xxx.jar
指令运行jar文件,会出现”no main manifest attribute, in xxx.jar”(没有设置Main-Class)、ClassNotFoundException(找不到依赖包)等错误。
要想jar包能直接通过java -jar xxx.jar
运行,需要满足:
1、在jar包中的META-INF/MANIFEST.MF中指定Main-Class,这样才能确定程序的入口在哪里;
2、要能加载到依赖包。
1. 使用maven-shade-plugin插件打包,该插件在maven实战中推荐使用。
<build>
<plugins> <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.xxg.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin> </plugins>
</build>
执行mvn package
即可打包。在target目录下会生成两个jar包,注意不是original-xxx.jar文件,而是另外一个,生成的jar文件包含了所有依赖,所以可以直接运行
不过如果项目中用到了Spring Framework,将依赖打到一个jar包中,运行时会出现读取XML schema文件出错。原因是Spring Framework的多个jar包中包含相同的文件spring.handlers和spring.schemas,如果生成单个jar包会互相覆盖。为了避免互相影响,可以使用AppendingTransformer
来对文件内容追加合并:
<build>
<plugins> <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.xxg.Main</mainClass>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlers</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.schemas</resource>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin> </plugins>
</build>
2. 使用maven-assembly-plugin插件打包
<build>
<plugins> <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.5</version>
<configuration>
<archive>
<manifest>
<mainClass>com.xxg.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin> </plugins>
</build> mvn package assembly:single
打包后会在target目录下生成一个xxx-jar-with-dependencies.jar
文件,这个文件不但包含了自己项目中的代码和资源,还包含了所有依赖包的内容。所以可以直接通过java -jar
来运行。
此外还可以直接通过mvn package
来打包,无需assembly:single
,不过需要加上一些配置:
<build>
<plugins> <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.5</version>
<configuration>
<archive>
<manifest>
<mainClass>com.xxg.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin> </plugins>
</build>
其中<phase>package</phase>
、<goal>single</goal>
表示在执行package打包时,执行assembly:single
,所以可以直接使用mvn package
打包。
不过,如果项目中用到Spring Framework,用这种方式打出来的包运行时会出现读取XML schema文件异常等奇怪的错误,使用上面的方法可以处理。
3.使用maven-jar-plugin和maven-dependency-plugin插件打包
<build>
<plugins> <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.xxg.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin> </plugins>
</build>
maven-jar-plugin用于生成META-INF/MANIFEST.MF文件的部分内容,<mainClass>com.xxg.Main</mainClass>
指定MANIFEST.MF中的Main-Class,<addClasspath>true</addClasspath>
会在MANIFEST.MF加上Class-Path项并配置依赖包,<classpathPrefix>lib/</classpathPrefix>
指定依赖包所在目录。
例如下面是一个通过maven-jar-plugin插件生成的MANIFEST.MF文件片段:
Class-Path: lib/commons-logging-1.2.jar lib/commons-io-2.4.jar
Main-Class: com.xxg.Main
不过仅仅生成MANIFEST.MF文件还不够,maven-dependency-plugin插件用于将依赖包拷贝到<outputDirectory>${project.build.directory}/lib</outputDirectory>
指定的位置,即lib目录下。
配置完成后,通过mvn package
指令打包,会在target目录下生成jar包,并将依赖包拷贝到target/lib目录下,目录结构如下:
目录结构
指定了Main-Class,有了依赖包,那么就可以直接通过java -jar xxx.jar
运行jar包。
不过这种方式生成jar包有个缺点,就是生成的jar包太多不便于管理,上边两种方式只生成单个jar文件,包含项目本身的代码、资源以及所有的依赖包。
4. assembly 引入配置式打包
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
<outputDirectory>${project.build.directory}/dubbo</outputDirectory>
<includes>META-INF/assembly/**</includes>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
aaarticlea/png;base64,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" alt="" /> <assembly>
<id>assembly</id>
<formats>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.build.directory}/dubbo/META-INF/assembly/bin</directory>
<outputDirectory>bin</outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>src/main/assembly/conf</directory>
<outputDirectory>conf</outputDirectory>
<fileMode>0644</fileMode>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
</dependencySet>
</dependencySets>
</assembly>
aaarticlea/png;base64,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" alt="" />