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包的方式的更多相关文章

  1. maven将项目及第三方jar打成一个jar包

    pom.xml中添加如下配置 把依赖包和自己项目的文件打包如同一个jar包(这种方式对spring的项目不支持) <build> <plugins> <plugin> ...

  2. Maven之多模块打包成一个jar包及assembly

    一.多模块打包 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ...

  3. 如何把一个java工程打成一个jar包(转载)

    1.jar包有入口(即有main()函数) 选中要打包的工程--->右键选择Export---->java----->Runnable java file----->next- ...

  4. Maven工程打成一个jar包

    1:maven-shade-plugin 插件 <plugin> <groupId>org.apache.maven.plugins</groupId> <a ...

  5. 使用Maven Assembly plugin将依赖打包进jar

    一个Eclipse的工程,在pom中配置了若干依赖,需要将pom中所有的依赖全部打包进一个jar包中,可以选择的方案有maven-assembly-plugin和fatjar.以前采用fatjar进行 ...

  6. Maven把项目依赖的所有jar包都打到同一个jar中

    目录 1 使用maven-shade-plugin 2 推荐: 使用maven-assembly-plugin 3 扩展: Maven安装本地jar包到本地仓库 4 扩展: 手动生成jar包 5 扩展 ...

  7. jstl Maven 依赖导致的 Jar 包冲突

    概述 Jar 包冲突是日常开发过程中,时常会遇到的问题.本文介绍由 jstl 的 Maven 依赖导致的 Jar 包冲突问题,以及对应的解决方法. jstl 的 Maven 依赖配置 <depe ...

  8. 今天遇到一个怪异的问题,maven生成项目war包中有一个Jar包不是我指定的版本,运行时会找不到符号,o(╥﹏╥)o

    我要求的jar包: 这是我parent项目中pom文件的依赖管理 这是我要生成war包那个工程最后依赖的jar包,这个时候它们的版本号还是一致的 最后项目生成的: 下图是Dmaven.test.ski ...

  9. maven 引用另一个jar包 需要先打包在仓库里面 并在pom里面配置 才可以引用

    maven 引用另一个jar包 需要先打包在仓库里面 并在pom里面配置 才可以引用

随机推荐

  1. 一、操作m'y's'ql

    一.创建framework框架的控制台默认不支持mysql

  2. Allow Only Ajax Requests For An Action In ASP.NET Core

    ASP.NET Core offers attributes such as [HttpGet] and [HttpPost] that allow you to restrict the HTTP ...

  3. vivado2016.1下载程序出错:End of startup status: LOW

    现象 使用JTAG下载程序,发现刚开始下载就出现了End of startup status: LOW错误.但能检测到芯片,证明JTAG没烧毁. 流程 前几次下载都没有问题,然后就有问题了. (1)怀 ...

  4. 升级AndroidStudio3.4问题汇总

    1.Could not get unknown property 'bootClasspath' for object of type org.gradle.api.tasks.compile.Com ...

  5. Linux命令_ls

    1.查看当前用户对某个指定路径的权限 ls -ld /some/path

  6. SpringMVC生命周期,SpringMVC运行流流程

    SpringMVC详细运行流程图 SpringMVC运行原理 1. 客户端请求提交到DispatcherServlet2. 由DispatcherServlet控制器查询一个或多个HandlerMap ...

  7. [C#] .NET4.0中使用4.5中的 async/await 功能实现异步

    在.NET Framework 4.5中添加了新的异步操作库,但是在.NET Framework 4.0中却无法使用.这时不免面临着抉择,到底是升级整个解决方案还是不使用呢? 如果你的软件还没发布出去 ...

  8. C# 类型转换的开销

    先来个测试: static void Main(string[] args) { Stopwatch stopwatch; string strStr = "string"; ob ...

  9. zipline-- 开发指南

    Development Guidelines开发指南This page is intended for developers of Zipline, people who want to contri ...

  10. 1、IDEA的常用快捷键

    一.常用的快捷键1.Ctrl+/ 或 Ctrl+Shift+/ 注释(// 或者/*...*/ )###2.Ctrl+D 复制行### 注意在MyEclipse中Ctrl+D的作用是删除行3.Ctrl ...