将Java应用程序打包为一个(或胖)JAR

这篇文章的目标是一个有趣但非常强大的概念:将应用程序打包为单个可运行的JAR文件,也称为一个 JAR文件。

我们习惯了大型WAR归档文件,其中包含所有打包在某些公用文件夹结构下的依赖项。 使用类似于JAR的打包,情况有所不同:为了使您的应用程序可运行(通过java -jar ),所有依赖项都应通过classpath参数或环境变量提供。 通常,这意味着将存在一些具有所有依赖项的lib文件夹和一些可运行的脚本 ,这些脚本将完成构造类路径和运行JVM的工作。 Maven Assembly插件因进行这种应用程序分发而闻名。

稍微不同的方法是将所有应用程序依赖项打包到同一JAR文件中,并使其可运行,而无需任何其他参数或脚本。 听起来不错,但是……除非您添加一些魔力,否则它将无法正常工作:满足One-JAR项目。

让我们简要概述一下问题:我们正在编写一个独立的Spring应用程序,只需键入java -jar <our-app.jar>即可运行该应用程序。

和往常一样,让我们​​从我们的POM文件开始,这将非常简单

<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.example</groupid><artifactid>spring-one-jar</artifactid><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>spring-one-jar</name><url>http://maven.apache.org</url><properties><project.build.sourceencoding>UTF-8</project.build.sourceencoding><org.springframework.version>3.1.1.RELEASE</org.springframework.version></properties><dependencies><dependency><groupid>cglib</groupid><artifactid>cglib-nodep</artifactid><version>2.2</version></dependency><dependency><groupid>org.springframework</groupid><artifactid>spring-core</artifactid><version>${org.springframework.version}</version></dependency><dependency><groupid>org.springframework</groupid><artifactid>spring-context</artifactid><version>${org.springframework.version}</version></dependency></dependencies>
</project>

我们的示例应用程序将引导Spring上下文,获取一些bean实例并在其上调用一个方法。 我们的bean叫做SimpleBean ,看起来像:

package com.example;
public class SimpleBean {public void print() {System.out.println( 'Called from single JAR!' );}
}

爱上Spring Java配置,让我们将上下文定义为带注释的AppConfig POJO:

package com.example.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import com.example.SimpleBean;@Configuration
public class AppConfig {@Beanpublic SimpleBean simpleBean() {return new SimpleBean();}
}

最后,我们的应用程序Startermain()

package com.example;import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;import com.example.config.AppConfig;public class Starter {public static void main( final String[] args ) {ApplicationContext context = new AnnotationConfigApplicationContext( AppConfig.class );SimpleBean bean = context.getBean( SimpleBean.class );bean.print();}
}

将我们的主类添加到META-INF / MANIFEST.MF可以利用Java功能来运行JAR文件,而无需使用main()方法显式指定类。 Maven JAR插件可以帮助我们。

<build><plugins><plugin><groupid>org.apache.maven.plugins</groupid><artifactid>maven-jar-plugin</artifactid><configuration><archive><manifest><mainclass>com.example.Starter</mainclass></manifest></archive></configuration></plugin></plugins>
</build>

尝试运行java -jar spring-one-jar-0.0.1-SNAPSHOT.jar会将异常输出到控制台: java.lang.NoClassDefFoundError 。 原因很简单:即使是这样一个简单的应用程序,也已经要求以下库位于类路径中。

aopalliance-1.0.jar
cglib-nodep-2.2.jar
commons-logging-1.1.1.jar
spring-aop-3.1.1.RELEASE.jar
spring-asm-3.1.1.RELEASE.jar
spring-beans-3.1.1.RELEASE.jar
spring-context-3.1.1.RELEASE.jar
spring-core-3.1.1.RELEASE.jar
spring-expression-3.1.1.RELEASE.jar

让我们在这里看看One-JAR可以为我们做些什么。 由于onejar-maven-plugin的可用性,我们可以在我们的POM文件的plugins部分中添加一个。

<plugin><groupid>org.dstovall</groupid><artifactid>onejar-maven-plugin</artifactid><version>1.4.4</version><executions><execution><configuration><onejarversion>0.97</onejarversion><classifier>onejar</classifier></configuration><goals><goal>one-jar</goal></goals></execution></executions>
</plugin>

另外, pluginRepositories部分应包含此存储库以便下载插件。

<pluginrepositories><pluginrepository><id>onejar-maven-plugin.googlecode.com</id><url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url></pluginrepository>
</pluginrepositories>

结果, 目标文件夹中将提供另一个工件,后缀有one-jarspring-one-jar-0.0.1-SNAPSHOT.one-jar.jar 。 使用java -jar spring-one-jar-0.0.1-SNAPSHOT.one-jar.jar运行此命令将打印到控制台:

Called from single JAR!

完全可运行的Java应用程序,作为单个可再发行的JAR文件! 最后的评论:尽管我们的应用程序看起来很简单,但是One-JAR也可以完美地用于复杂的大型应用程序。 请把它添加到您的工具箱中,它是非常有用的工具。

感谢One-JAR伙计们!

参考: 简单但功能强大的概念:在Andriy Redko {devmind}博客上,从我们的JCG合作伙伴 Andrey Redko 将Java应用程序打包为一个(或胖)JAR 。

翻译自: https://www.javacodegeeks.com/2012/11/packing-your-java-application-as-one-or-fat-jar.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/370479.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学习java的第三天,猜字符的小程序

关于猜字符的小程序 主要实现&#xff1a;随机输出5个字母&#xff0c;用户输入猜测的字母&#xff0c;进行对比得出结果 主要有3个方法&#xff1a;主方法main(); 产生随机字符的方法generate(); 比较用户输入的字符与随机产生的字符的方法check&#xff08;&#xff09;&…

《Linux命令行与shell脚本编程大全 第3版》创建实用的脚本---10

以下为阅读《Linux命令行与shell脚本编程大全 第3版》的读书笔记&#xff0c;为了方便记录&#xff0c;特地与书的内容保持同步&#xff0c;特意做成一节一次随笔&#xff0c;特记录如下&#xff1a;转载于:https://www.cnblogs.com/guochaoxxl/p/7894995.html

python安装包找不到setup_如何安装没有setup.py的Python模块?

在系统上开始使用该代码的最简单的方法是&#xff1a;>将文件放入机器上的目录中,>将该目录的路径添加到您的PYTHONPATH步骤2可以从Python REPL完成如下&#xff1a;import syssys.path.append("/home/username/google_search")您的文件系统的外观示例&#xf…

Spring Batch中面向TaskletStep的处理

许多企业应用程序需要批处理才能每天处理数十亿笔交易。 必须处理这些大事务集&#xff0c;而不会出现性能问题。 Spring Batch是一个轻量级且强大的批处理框架&#xff0c;用于处理这些大数据集。 Spring Batch提供了“面向TaskletStep”和“面向块”的处理风格。 在本文中&a…

布局中常见的居中问题

说到布局除了浮动以及定位外还有一个不得不提的点&#xff0c;那就是居中&#xff0c;居中问题我们在网页布局当中经常遇到&#xff0c;那么以下就是分为两部分来讲&#xff0c;一部分是传统的居中&#xff0c;另一种则是flex居中&#xff0c;每个部分又通过分为水平垂直居中来…

unity json解析IPA后续

以前说到的&#xff0c;有很大的限制&#xff0c;只能解析简单的类&#xff0c;如果复杂的就会有问题&#xff0c;从老外哪里看到一片博客&#xff0c;是将类中的list 等复杂对象序列化&#xff0c; using UnityEngine; using System.Collections; using System.Collections.…

改善代码质量之内连临时变量

待增转载于:https://www.cnblogs.com/muyl/articles/6940896.html

python 矩阵元素相加_Numpy中元素级运算

标量与矩阵的运算:加法&#xff1a;values [1,2,3,4,5]values np.array(values) 5#现在 values 是包含 [6,7,8,9,10] 的一个 ndarray乘法&#xff1a;x np.multiply(some_array, 5)x some_array * 5矩阵与矩阵的运算:加法&#xff1a;对应元素相加&#xff0c;但形状必须相…

排序算法——桶排序

把数据放进若干个桶&#xff0c;然后在桶里用其他排序&#xff0c;近乎分治思想。从数值的低位到高位依次排序&#xff0c;有几位就排序几次。例如二位数就排两次&#xff0c;三位数就排三次&#xff0c;依次按照个十百...的顺序来排序。 第一次排序&#xff1a;50 12 …

原型设计模式:创建另一个小车

创建对象确实是一个耗时的过程&#xff0c;也是一件昂贵的事情。 因此&#xff0c;我们现在正努力节省时间和金钱。 我们该怎么做&#xff1f; 克隆奇迹多莉 有人记得多莉吗&#xff1f; 是的&#xff0c;是绵羊&#xff0c;是第一个被克隆的哺乳动物。 好吧&#xff0c;我不想…

java实现周期任务_java定时任务的实现方式

本文列举常见的java定时任务实现方式&#xff0c;并做一定比较。1. 循环内部sleep实现周期执行创建一个thread&#xff0c;run() while循环里sleep()来实现周期性执行; 简单粗暴&#xff0c;作为一个初学者很容易想到。public class Task1 {public static void main(String[] a…

磁盘镜像工具Guymager

磁盘镜像工具Guymager在数字取证中&#xff0c;经常需要对磁盘制作镜像&#xff0c;以便于后期分析。Kali Linux提供一款轻量级的磁盘镜像工具Guymager。该工具采用图形界面化方式&#xff0c;提供磁盘镜像和磁盘克隆功能。它不仅生成dd的镜像&#xff0c;还能生成EWF和AFF镜像…

python怎么写代码求年华收益率_如何计算年化收益率?

关于投资年化收益率的计算&#xff0c;三思君觉得主要有三种&#xff0c;分别是一次性投资的收益率计算、定期定额的收益率计算、不定期不定额的收益率计算。1.一次性投资的收益率计算对于一次性投资的收益率&#xff0c;相信大家都会计算。比如&#xff0c;小李同学去年买了一…

HTTPS协议在Tomcat中启用的配置

本文将讲解HTTPS协议在Tomcat中启用是如何配置的。 概念简介 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器&#xff0c;属于轻量级应用服务器&#xff0c;在中小型系统和并发访问用户不是很多的场合下被普遍使用&#xff0c;是开发和调试 JSP 程序的首选。 HTTP 超文本…

CSS3实现烟花特效 --web前端

烟花特效&#xff0c;比较简单&#xff0c;直接贴代码了……<!DOCTYPE html><html lang"en"><head> <meta charset"UTF-8"> <title>css3实现烟花特效</title> <style> * { margin: 0; padding: 0; } html{ widt…

虚拟机 java 开发_深入浅出 Java 虚拟机 · 通往高级 Java 开发的必经之路

第一章 JVM 内存模型Java 虚拟机(Java Virtual MachineJVM)的内存空间分为五个部分&#xff0c;分别是&#xff1a;程序计数器Java 虚拟机栈本地方法栈堆方法区。下面对这五个区域展开深入的介绍。1.1 程序计数器1.1.1 什么是程序计数器&#xff1f;程序计数器是一块较小的内存…

java.lang.ClassNotFoundException:如何解决

本文适用于当前面临java.lang.ClassNotFoundException挑战的Java初学者。 它将为您提供此常见Java异常的概述&#xff0c;这是一个示例Java程序&#xff0c;可支持您的学习过程和解决策略。 如果您对与更高级的类加载器相关的问题感兴趣&#xff0c;我建议您复习有关java.lang…

iOS10 App跳转到系统设置

实现类似万能钥匙中点击一个Wi-Fi跳转到系统Wi-Fi设置界面的功能。 NSString * urlString "App-Prefs:rootWIFI";if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:urlString]]) {if ([[UIDevice currentDevice].systemVersion doubleValue…

python生成器 图片分类_python批量处理图片图片Python迭代器和生成器介绍

Python迭代器和生成器介绍迭代器迭代器是一个实现了迭代器协议的对象&#xff0c;Python中的迭代器协议就是有next方法的对象会前进到下一结果&#xff0c;而在一系列结果的末尾是&#xff0c;则会引发StopIteration。在for循环中&#xff0c;Python将自动调用工厂函数iter()获…

Java-IO流之BufferedReader 和BufferedWriter的使用和原理

BufferedReader和BufferedWriter出现的目的是为了对FileReader以及FileWriter的读写操作进行增强&#xff0c;而怎么增强呢&#xff0c;原理类似于使用StringBuilder&#xff0c;是把数据先放入他们的一个char数组中&#xff0c;然后再操作char数组。 使用缓冲区的字符流是使用…