前言
关于使用maven将java代码打包成jar包,我之前一直是使用mvn package
命令。不过也经常会遇到问题,例如打包的时候是依赖一起打包进来还是把依赖放在特定的目录,打包的时候指定主类等。所以我在网上找了一些文章,学习了一下maven打包的方式。
maven打包命令
首先使用maven打jar包最常用的命令就是mvn package
,但是使用mvn install
、mvn deploy
命令也都可以对项目进行打包,不过这几条命令都有区别:
mvn package
:完成项目的编译、测试、打包mvn install
:完成项目的编译、测试、打包之后将打好的jar包部署到本地仓库mvn deploy
:完成项目的编译、测试、打包之后将打好的jar包部署到远程仓库
在完成打包之后使用java -jar
命令运行jar包的时候很有可能会出现找不到主类清单的报错。这个时候也有两种解决方法,首先可以尝试使用java -cp
命令:
|
|
另一种方法是在META-INF\MANIFEST.MF
文件中指定Main-Class
的名称,这样在执行java -jar
的时候就会根据MANIFEST.MF
中Main-Class
的值找到要执行的类。然后我现在想让maven在打包的时候自动帮我在MANIFEST.MF
文件中加上这个Main-Class
。
maven打包插件
maven常用的打包插件有主要有下面这几种
maven-jar-plugin
和maven-dependency-plugin
maven-jar-plugin
和maven-dependency-plugin
是默认的打包插件
maven-jar-plugin
负责将项目打包成jar包,并且可以给MANIFEST.MF
加上一些自定义的属性,例如Main-Class
用于指定启动类,Class-Path
由于指定去哪个路径找依赖包maven-dependency-plugin
就是负责处理依赖包的,它可以指定打包后项目中使用到的依赖包需要放在哪个目录
一般情况下maven-jar-plugin
和maven-dependency-plugin
会同时使用。
然后怎么使用maven-jar-plugin
和maven-dependency-plugin
呢,这里有几个例子理解maven-jar-plugin
和maven-dependency-plugin
打包,并向其中添加Main-Class
属性。
指定manifestFile
首先可以尝试自己创建一个
META-INF/MANIFEST.MF
文件,然后向其中添加Main-Class
属性:1
Main-Class: org.e4stjun.Main
接着在
pom.xml
文件中用manifestFile
指定MANIFEST.MF
文件的路径,在打包后就会把MANIFEST.MF
文件打包进去,如果有其他属性要加进来的话会追加:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
<build> <!-- 指定打包后的文件名--> <finalName>Mavencmd-1.0-SNAPSHOT</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.3.0</version> <configuration> <archive> <manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile> </archive> </configuration> </plugin> </plugins> </build>
在
pom.xml
里面添加manifest
属性这样子就是说通过标签向
MANIFEST.MF
添加一些属性,不用自己创建了,让maven自动帮我创建1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.3.0</version> <configuration> <archive> <manifest> <mainClass>org.e4stjun.Main</mainClass> </manifest> </archive> </configuration> </plugin> </plugins> </build>
打包时将依赖复制到lib目录:
如果项目中引入了一些依赖的话就需要同时使用
maven-jar-plugin
和maven-dependency-plugin
两个插件了,maven-jar-plugin
中指定主类,除此之外还要告诉jar包去哪个目录找引入依赖的jar包,而maven-dependency-plugin
将项目依赖的jar包复制到指定目录,例如在这个例子里面打包的jar包去./lib
目录找到依赖包,maven-dependency-plugin
将依赖复制到输出目录的lib
文件夹中:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
<build> <finalName>Mavencmd-1.0-SNAPSHOT</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.3.0</version> <configuration> <archive> <manifest> <!-- 指定主类 --> <mainClass>org.e4stjun.Main</mainClass> <!-- 是否指定项目classpath下的依赖 --> <addClasspath>true</addClasspath> <!-- 指定依赖的时候声明前缀 --> <classpathPrefix>./lib/</classpathPrefix> <!--依赖是否使用带有时间戳的唯一版本号,如:xxx-1.3.0-20121225.012733.jar--> <useUniqueVersions>false</useUniqueVersions> </manifest> </archive> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>3.6.0</version> <executions> <execution> <id>copy</id> <phase>package</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory>${project.build.directory}/lib</outputDirectory> </configuration> </execution> </executions> </plugin> </plugins> </build>
maven-assembly-plugin
这个插件打包出来的只有一个jar包,可以通过java -jar
直接执行,
使用
mvn package assembly:single
命令打包:同样还是先要指定
Main-Class
,然后打包完会在输出文件夹中生成一个xxx-jar-with-dependencies.jar
文件,包含项目中所有的依赖,通过java -jar
命令可以直接执行:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.6.0</version> <configuration> <archive> <!-- 指定启动类 --> <manifest> <mainClass>org.e4stjun.Main</mainClass> </manifest> </archive> <!-- Maven预配置的描述符 --> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> </plugin> </plugins> </build>
mvn package
打包,不加assembly:single
参数:这样的话需要再多写一个
execution
块:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.6.0</version> <configuration> <archive> <!-- 指定启动类 --> <manifest> <mainClass>org.e4stjun.Main</mainClass> </manifest> </archive> <!-- Maven预配置的描述符 --> <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>
引入
assembly.xml
描述文件还有一种是在
pom.xml
文件中引入assembly.xml
描述文件:1 2 3 4 5
<configuration> <descriptors> <descriptor>src/main/assembly/assembly.xml</descriptor> </descriptors> </configuration>
maven官方的文档在这里:https://maven.apache.org/plugins/maven-assembly-plugin/assembly.html
在某一个场景下,我需要将
scope
为system的依赖打包进jar包这个时候我需要在assembly.xml
描述文件中添加这一段:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 https://maven.apache.org/xsd/assembly-2.2.0.xsd"> <id>jar-with-all-dependencies</id> <formats> <format>jar</format> </formats> <includeBaseDirectory>false</includeBaseDirectory> <dependencySets> <dependencySet> <outputDirectory>/</outputDirectory> <useProjectArtifact>true</useProjectArtifact> <unpack>true</unpack> <scope>runtime</scope> </dependencySet> <dependencySet> <outputDirectory>/</outputDirectory> <unpack>true</unpack> <scope>system</scope> </dependencySet> </dependencySets> </assembly>
在使用maven打包的时候就会将需要的jar包也打包进去了。
maven-shade-plugin
maven-shade-plugin
也是一个很强大的打包插件,主要是可以用来处理依赖冲突的问题,这里我给一个例子出来:
|
|