Maven将代码及依赖打成一个Jar包的方式
Maven可以使用mvn package指令对项目进行打包,如果使用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、要能加载到依赖包。
使用Maven有以下几种方法可以生成能直接运行的jar包并且是打成一个jar包,可以根据需要选择一种合适的方法。
方法一:使用maven-assembly-plugin插件打包
在pom.xml中配置:
<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(在eclipse中执行maven build…… ,然后在Goals中输入 assembly:single)
打包后会在target目录下生成一个xxx-jar-with-dependencies.jar文件,这个文件不但包含了自己项目中的代码和资源,还包含了所有依赖包的内容。所以可以直接通过java -jar来运行。
此外还可以直接通过mvn package来打包(在eclipse中直接执行maven install),无需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><!-- 这个jar-with-dependencies是assembly预先写好的一个,组装描述引用 --><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs> <!--工程名--> <finalName>${project.name}</finalName></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,用这种方式打出来的包运行时会出错,使用下面的方法二可以处理。
方法二:使用maven-shade-plugin插件打包
在pom.xml中配置:
<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文件,而是另外一个。和maven-assembly-plugin一样,生成的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>
方法三:使用maven-jar-plugin和maven-dependency-plugin插件打包
原理是通过修改maven 打jar包的maven-jar-plugin插件的配置信息来生成我们需要的指定依赖的可执行jar包。
在项目的pom.xml文件中修改默认的jar插件
<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>2.3.1</version><configuration><archive><manifest><!--运行jar包时运行的主类,要求类全名--><mainClass>com.hafiz.Runner</mainClass><!-- 是否指定项目classpath下的依赖 --><addClasspath>true</addClasspath><!-- 指定依赖的时候声明前缀 --><classpathPrefix>./lib/</classpathPrefix><!--依赖是否使用带有时间戳的唯一版本号,如:xxx-1.3.0-20121225.012733.jar--><useUniqueVersions>false</useUniqueVersions></manifest></archive></configuration></plugin></plugins></build><!--接着我们还要配置maven的maven-dependency-plugin插件把当前项目的所有依赖放到target目录下的lib文件夹下--><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId><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>
其中,${project.build.directory}表示默认的target文件夹。
我们通过上文的修改便完成了适用maven生成指定依赖的可执行jar包。
我们发现生成的manifest文件中已经设置好了Main-Class以及Class-Path,如下:
如果<addClasspath>设置为false,则生成的manifest文件中不会声明依赖(即不会有Class-Path声明)
程序主类如下:
package com.hafiz;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;/*** Desc:主类* Created by hafiz.zhang on 2018/4/07.*/public class Runner {public static void main(String[] args) {ApplicationContext context= new ClassPathXmlApplicationContext("classpath:applicationContext.xml");System.out.println("context:" + context.getClass());System.out.println("The Main Class Is Running....");}}
pom.xml文件如下:
<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>com.hafiz</groupId><artifactId>assembly-demo</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><name>assembly-demo</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring.version>4.2.6.RELEASE</spring.version></properties><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-expression</artifactId><version>${spring.version}</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>2.3.1</version><configuration><archive><manifest><!--运行jar包时运行的主类,要求类全名--><mainClass>com.hafiz.Runner</mainClass><!-- 是否指定项目classpath下的依赖 --><addClasspath>true</addClasspath><!-- 指定依赖的时候声明前缀 --><classpathPrefix>./lib/</classpathPrefix><!--依赖是否使用带有时间戳的唯一版本号,如:xxx-1.3.0-20121225.012733.jar--><useUniqueVersions>false</useUniqueVersions></manifest></archive></configuration></plugin><!--把当前项目所有的依赖打包到target目录下的lib文件夹下--><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId><executions><execution><id>copy</id><phase>package</phase><goals><goal>copy-dependencies</goal></goals><configuration><outputDirectory>${project.build.directory}/lib</outputDirectory><!--已存在的Release版本不重复copy--><overWriteReleases>false</overWriteReleases><!--已存在的SnapShot版本不重复copy--><overWriteSnapshots>false</overWriteSnapshots><!--不存在或者有更新版本的依赖才copy--><overWriteIfNewer>true</overWriteIfNewer></configuration></execution></executions></plugin></plugins></build></project>
我们现在进入生成的jar包所在的文件夹下,使用 java -jar xxx.jar来执行生成的jar包
到此我们就完成了如何使用maven的jar包生成插件来进行生成指定依赖的可执行jar包。
代码Github地址:https://github.com/hafizzhang/assembly-demo.git
参考网址:
https://blog.csdn.net/xiao__gui/article/details/47341385
http://www.cnblogs.com/hafiz/p/6538107.html
https://www.cnblogs.com/hafiz/p/6538332.html
Maven将代码及依赖打成一个Jar包的方式的更多相关文章
- maven将项目及第三方jar打成一个jar包
pom.xml中添加如下配置 把依赖包和自己项目的文件打包如同一个jar包(这种方式对spring的项目不支持) <build> <plugins> <plugin> ...
- Maven之多模块打包成一个jar包及assembly
一.多模块打包 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ...
- 如何把一个java工程打成一个jar包(转载)
1.jar包有入口(即有main()函数) 选中要打包的工程--->右键选择Export---->java----->Runnable java file----->next- ...
- Maven工程打成一个jar包
1:maven-shade-plugin 插件 <plugin> <groupId>org.apache.maven.plugins</groupId> <a ...
- 使用Maven Assembly plugin将依赖打包进jar
一个Eclipse的工程,在pom中配置了若干依赖,需要将pom中所有的依赖全部打包进一个jar包中,可以选择的方案有maven-assembly-plugin和fatjar.以前采用fatjar进行 ...
- Maven把项目依赖的所有jar包都打到同一个jar中
目录 1 使用maven-shade-plugin 2 推荐: 使用maven-assembly-plugin 3 扩展: Maven安装本地jar包到本地仓库 4 扩展: 手动生成jar包 5 扩展 ...
- jstl Maven 依赖导致的 Jar 包冲突
概述 Jar 包冲突是日常开发过程中,时常会遇到的问题.本文介绍由 jstl 的 Maven 依赖导致的 Jar 包冲突问题,以及对应的解决方法. jstl 的 Maven 依赖配置 <depe ...
- 今天遇到一个怪异的问题,maven生成项目war包中有一个Jar包不是我指定的版本,运行时会找不到符号,o(╥﹏╥)o
我要求的jar包: 这是我parent项目中pom文件的依赖管理 这是我要生成war包那个工程最后依赖的jar包,这个时候它们的版本号还是一致的 最后项目生成的: 下图是Dmaven.test.ski ...
- maven 引用另一个jar包 需要先打包在仓库里面 并在pom里面配置 才可以引用
maven 引用另一个jar包 需要先打包在仓库里面 并在pom里面配置 才可以引用
随机推荐
- POJ1847 Tram
Tram Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 20274 Accepted: 7553 Description ...
- C# 使用CsvHelper读取.csv文件
1,先到包管理器下载 安装CsvHelper. 2,创建一个与csv文件字段名称相同的类 public class SurveyInfoModel { public string DIST_CD { ...
- [ffmpeg] 滤波
ffmpeg中有很多已经实现好的滤波器,这些滤波器的实现位于libavfilter目录之下,用户需要进行滤波时,就是是调用这些滤波器来实现的.ffmpeg对于调用滤波器有一整套的调用机制. 基本结构 ...
- Java 获取当前线程、进程、服务器ip
/** * 获取当前线程id */ private Long getThreadId() { try { return Thread.currentThread().getId(); } catch ...
- Linux-KVM虚拟化
kvm安装 1.在宿主机上准备好yum(只需要本地镜像yum就可以) 2.查看CPU是否支持inter或AMD的虚拟技术 # cat /proc/cpuinfo |grep -E "vmx| ...
- 牛客小白月赛13-J小A的数学题 (莫比乌斯反演)
链接:https://ac.nowcoder.com/acm/contest/549/J来源:牛客网 题目描述 小A最近开始研究数论题了,这一次他随手写出来一个式子,∑ni=1∑mj=1gcd(i,j ...
- Java 8 特性 —— 函数式接口
函数式接口 概述:接口中只有一个抽象方法. 函数式接口,即适用于函数式编程场景的接口.而 Java 中的函数式编程体现就是 Lambda,所以函数式接口就是可以适用于 Lambda 使用的接口.只有确 ...
- 大二学生党的Security+备考宝典(一次过)
刚出成绩的一刹那,我的心里是慌的很的,因为可能知识点复习的不够扎实,考试上的题目全都回归了课本,而我的知识回归了老师(滑稽),一下给大家分享下我的经验,希望大家引以为戒,都能考出好成绩. 一.直播阶段 ...
- 基于 Markdown 编写接口文档
最近公司开发项目需要前后端分离,这样话就设计到后端接口设计.复杂功能需要提供各种各样的接口供前端调用,因此编写API文档非常有必要了 网上查了很多资料,发现基于Markdown编写文档是一种比较流行而 ...
- Apache 解析.htaccess
解决.htaccess不解析 输入a2enmod rewrite 修改/etc/apache.conf 此处改为ALL