1 简介

大家都知道java项目可以打包成一个可执行的jar包,当我们指定程序的入口main后,可以利用 java -jar YourApp.jar 命令运行可执行jar。那么它需要什么条件才能运行呢?在eclipse java工程和maven工程该怎么打包和部署呢?下面将一一解答。

1.1 运行java -jar app.jar命令的背后

当我们在命令窗口运行java -jar app.jar时,虚拟机做了什么事呢?其实要解答这个问题,就要深入类加载器机制,这已经超出了本文的范围。我们只需要知道,虚拟机使用多个类加载器加载class文件。其中app CLassLoader会获取jar包中的 META-INF/MANIFEST.MF文件,并加载文件中指定的class文件。MANIFEST.MF文件列出了该jar包需要依赖的jar包、可执行jar的入口程序,版本号等。

MANIFEST.MF如下图所示:

java 可执行java java调用可执行jar包_开发工具

至于MANIFEST.MF的格式和如何编写不在本文的范围。

  • ** Manifest-Version ** 清单文件的版本
  • ** Main-Class ** 主程序所在class的全路径
  • ** Class-Path ** 可执行jar依赖的包路径,所指的路径与可执行文件同一目录路径

1.2 需求

** 目的:可执行JAR在控制台输出字符串,主程序中依赖apache的commons-lang3包对字符串进行拼接**

package com.github.thinwonton.jarstarter;

import org.apache.commons.lang3.StringUtils;

public class JarStarterMain {
	public static void main(String[] args) {
		String string = StringUtils.join("JarStarterMain--->", "main"); // 合并字符串
		System.out.println(string);
	}
}

最终jar包和第三方jar所在的目录结构

JarStarter
    JarStarter.jar
    lib
        commons-lang3-3.5.jar

** 运行结果 **

java 可执行java java调用可执行jar包_开发工具_02

2 eclipse导出可执行jar文件

java工程结构

java 可执行java java调用可执行jar包_java 可执行java_03

** 创建自定义MANIFEST.MF文件**

文件内容如下,注意文件最后需要空两行,否则导出jar时,eclipse不会包含Main-Class这行。

Manifest-Version: 1.0
Main-Class: com.github.thinwonton.jarstarter.JarStarterMain
Class-Path: ./lib/commons-lang3-3.5.jar

** 使用eclipse的jar导出功能 **

java 可执行java java调用可执行jar包_jar_04

java 可执行java java调用可执行jar包_开发工具_05

java 可执行java java调用可执行jar包_jar_06

这时可执行jar已经导出到 f:/JarStarter 文件夹中,我们再把工程所依赖的jar包复制到 f:/JarStarter/lib 文件夹就可用命令jar -jar JarStarter.jar 运行了。

3 maven工程编译可执行jar文件

要编译和打包可执行jar文件,需要借助maven的两个插件:maven-jar-plugin和maven-dependency-plugin。前一个是打包可执行jar文件的,后一个是拷贝依赖包的。下面是它们的具体用法。

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.github.thinwonton.java</groupId>
	<artifactId>jarstarter-maven</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<dependencies>
		<!-- 工具 -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.5</version>
		</dependency>
	</dependencies>

	<build>
		<!-- 输出文件名 -->
		<finalName>jarstarter</finalName>

		<plugins>

			<!-- 资源文件拷贝插件 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-resources-plugin</artifactId>
				<version>2.7</version>
				<configuration>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>

			<!-- java编译插件 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.2</version>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>

			<!-- 打包jar文件时,配置manifest文件,加入lib包的jar依赖 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-jar-plugin</artifactId>
				<version>2.6</version>
				<configuration>
					<classesDirectory>target/classes/</classesDirectory>
					<archive>
						<manifest>
							<!-- 打包时 MANIFEST.MF文件不记录的时间戳版本 -->
							<useUniqueVersions>false</useUniqueVersions>
							<!-- 添加Class-Path -->
							<addClasspath>true</addClasspath>
							<!-- Class-Path添加前缀 -->
							<classpathPrefix>lib/</classpathPrefix>
							<!-- 指定Main-Class -->
							<mainClass>com.github.thinwonton.jarstarter.JarStarterMain</mainClass>
						</manifest>
					</archive>
				</configuration>
			</plugin>

			<!-- 拷贝依赖的jar包到lib目录 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-dependency-plugin</artifactId>
				<version>2.10</version>
				<executions>
					<execution>
						<id>copy</id>
						<phase>package</phase>
						<goals>
							<goal>copy-dependencies</goal>
						</goals>
						<configuration>
							<outputDirectory>
							    <!-- 拷贝依赖到lib文件夹 -->
								${project.build.directory}/lib
							</outputDirectory>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>

</project>

在工程根目录下运行 mvn clean package ,这时maven构建工具会在target文件夹中生成 jarstarter.jar 文件 和 lib文件夹,lib文件夹包含有工程所依赖的jar包。 这时jarstarter.jar的清单文件内容:

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: Administrator
Class-Path: commons-lang3-3.5.jar
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_102
Main-Class: com.github.thinwonton.jarstarter.JarStarterMain

4 参考资料

本文涉及代码

项目中的jarstarter和jarstarter-maven工程