一罐来统治所有人

跳下内存通道

早在1998年,当我是一名C / C ++开发人员时,尝试使用Java时,有关该语言的一些内容对我来说就显得有些恼火了。 我记得很担心这些

  1. 为什么没有合适的编辑器呢? C / C ++有很多。 我为Java拥有的只是旧的记事本。
  2. 当我想要的只是一个函数时,为什么我必须上一堂课? 为什么函数也不是对象?
  3. 为什么我不能将所有内容打包到一个zip / jar中,然后让最终用户双击启动?

和其他一些。 那时,我发现自己经常因为无法放弃自己的“ C / C ++思维方式”和拥抱“ Java方式”而自欺欺人。 现在,大约在十年半后的2013年写这篇文章,令人惊讶的是,所有这些早期的烦恼都消失了。 不是因为我采用了“ Java”方式,而是因为Java发生了变化。

除了闲聊之外,本文的重点是讨论以下问题之一:“为什么我不能将所有内容打包到一个zip / jar中,让最终用户双击启动?”。

为什么我们需要一个可执行的zip / jar文件?

如果您是开发人员,请在您的IDE上愉快地编码(我鄙视所有从Eclipse开始使用Java编码,NetBeans从一开始就不必在记事本上编码的人),并在Google的帮助下(我非常讨厌所有人) (他们不必在Google之前就可以在互联网上找到东西),可能没有令人信服的案例。

但是,当您遇到一种情况时

  1. 您之所以进入数据中心,是因为那里的人遵循了您的部署步骤,但是您的应用程序/网站根本无法正常工作?
  2. 突然之间,当“根本没有人碰到”生产箱时,环境变量全部搞砸了,而您就是必须“使其正常工作”的人。
  3. 您正与业务利益相关者坐在一起,难以置信地盯着“ ClassNotFound例外”,并确信Java根本不喜欢您。

简而言之,我想说的是,当您处于开发箱/环境的“相对”理智状态时,一个可执行的jar并不会真正为您做任何事情。 但是,当您进入未知服务器和情况的黄昏区域(没有IDE和其他工具的情况)时,您就会开始意识到单个可执行jar可以提供多少帮助。

不是吗

我天真地这么想,并以艰难的方式找到了答案。 让我一窥。 激发您的编辑人员。 让我们创建一个可执行的Jar项目。 我使用jdk1.7.0,STS,Maven 3.0.4。 如果您是Maven的新手或刚开始使用,我建议您阅读
这个和这个 。

档案:C:\ projects \ MavenCommands.bat

ECHO OFF
REM =============================
REM Set the env. variables.
REM =============================
SET PATH=%PATH%;C:\ProgramFiles\apache-maven-3.0.4\bin;
SET JAVA_HOME=C:\ProgramFiles\Java\jdk1.7.0
REM =============================
REM Standalone java application.
REM =============================
call mvn archetype:generate ^
-DarchetypeArtifactId=maven-archetype-quickstart ^
-DinteractiveMode=false ^
-DgroupId=foo.bar ^
-DartifactId=executableJar001
pause

运行此批处理文件后,您将拥有一个完全可编译的标准Java应用程序。 继续编译它并构建一个jar(mvn -e clean install)。 您将在C:\ projects \ executableJar001 \ target下获得一个可执行文件Jar001-1.0-SNAPSHOT.jar。 现在放手'
java -jar jarFileName '。 在这里,您第一次跌倒。 在令人讨厌的词汇表中,它告诉您不存在带有main方法的类,因此它不知道该执行什么。 幸运的是,这很容易。 有标准的Java程序可以解决它。 并且有一个Maven插件可以解决它。 我将使用后者。

更新的文件:/executableJar001/pom.xml

...<dependencies>...</dependencies><build><plugins><!-- Set main class in the jar. --><plugin><groupid>org.apache.maven.plugins</groupid><artifactid>maven-jar-plugin</artifactid><version>2.4</version><configuration><archive><manifest><mainclass>foo.bar.App</mainclass></manifest></archive></configuration></plugin></plugins></build>...

您可以再次编译和组装应用程序(mvn -e clean install)。 它会在目标文件夹中创建一个jar文件。 尝试再次从命令行运行jar 。 这次您将获得预期的结果。 所以,我们都被排序了,对吧? 错误。 错了

一切似乎都很好。

让我们深入研究一下,我们会发现为什么现在所有的东西都不像现在看起来那样排序。 让我们继续添加一个依赖,例如,假设我们要添加日志记录,为此我们要使用第三方jar,即logback。 我将让Maven处理开发环境中的依赖项。

更新的文件:/executableJar001/pom.xml

...<dependencies><!-- Logging --><dependency><groupid>ch.qos.logback</groupid><artifactid>logback-classic</artifactid><version>1.0.9</version></dependency></dependencies><build>... </build>

更新的文件:/executableJar001/src/main/java/foo/bar/App.java

package foo.bar;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class App 
{private final static Logger logger = LoggerFactory.getLogger(App.class);public static void main( String[] args ){System.out.println( 'Hello World!' );logger.debug('Hello world from logger.');}
}

现在,让我们使用jar命令从命令提示符处编译并运行jar。 你看到发生了什么事吗?

Exception in thread 'main' java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory

基本上是说找不到LoggerFactory的类(即实际代码)(即我们在开发环境中添加的第3方jar)。

哦,但是可以肯定的是,我们应该能够告诉Java从某个文件夹中提取第三方库。

绝对是 如果您要问这个问题,几乎可以肯定的是,对于大多数应用程序,您都告诉JVM第三方/依赖库在哪里。 您可以通过设置classpath来告知。 您可能正在使用某些应用程序服务器,例如Tomcat / Jetty,而这本身可能是一些依赖项。 而这正是问题的根源。

作为开发人员,我提供了一个有效的x.jar。 但是,要使其正常工作,它取决于a.jar(这反过来可能取决于b.jar和c.jar……您明白了)。 当我作为开发人员将我的可交付成果x.jar捆绑在一起时,存在依赖关系-取决于我将其分发给谁-确保在应该使用x.jar的其他环境中正确设置类路径上班。

多数情况下这没什么大不了的。 但是,这也不是小事。 有多种方法可以弄乱对目标环境的依赖性。 可能会有例行更新。 在同一生产环境中可能还部署了其他一些应用程序,需要在jar上进行更新,没人认为会影响您的。 我们可以讨论和辩论多种方法来阻止此类不幸事件,但是最重要的是x.jar(开发人员责任)具有依赖性(开发人员不直接控制)。 这会导致不幸。

当然,如果将由于不同版本,不同应用服务器等导致的全部变量添加到此混合中,那么仅提供x.jar的现有解决方案很快就会显得非常脆弱。

那么我们该怎么办?

对P. Simon Tuffs博士表示感谢。 这位先生在此环节解释了他如何迎合这个问题。 这是一本好书,我推荐。 我用非常普通的方式解释过的(几乎没有刮过表面),Simon深入探讨了该问题及其解决方法。 长话短说, 他编写了一个解决方案并将其开源 。 我将不再重播相同的信息-阅读他的文章 ,内容非常丰富-但我将指出他解决方案的重点。

  1. 它使人们可以创建一个包含所有内容(包括代码,资源,依赖项,应用程序服务器(可能))的jar。
  2. 它允许最终用户通过简单的java -jar jarFileName命令来运行整个humongous jar。
  3. 它允许开发人员以与开发相同的方式进行开发,例如,如果是Web应用程序,war文件结构将保持不变。 因此,在开发过程中没有任何变化。

那么我们如何去做呢?

在很多地方都有详细的说明。 One-JAR网站 。 与One-JAR的蚂蚁 。 具有一罐的Maven 。

让我们看看它在我们的伪代码上的作用。 值得庆幸的是,还有一个Maven插件 。 遗憾的是,它不在Maven Central存储库中(为什么?伙计们为什么?您投入了98%的工作。为什么对最后2%的工作比较迟钝?)。 它带有不错的
使用说明 。

更新的文件:/executableJar001/pom.xml

...<dependencies>... </dependencies><build><plugins>...<!-- If you wanted to bundle all this in one jar. --><plugin><groupid>org.dstovall</groupid><artifactid>onejar-maven-plugin</artifactid><version>1.4.4</version><executions><execution><goals><goal>one-jar</goal></goals></execution></executions></plugin></plugins></build><!-- Required only if you are usng onejar plugin. --><pluginrepositories><pluginrepository><id>onejar-maven-plugin.googlecode.com</id><url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url></pluginrepository></pluginrepositories>

现在您需要做的就是运行mvn -e clean package。 除了普通的广口瓶外,您还会得到一个脂肪充足的广口瓶。 继续,再次从命令提示符处执行java -jar jarFileName。 它应该工作。

嗯..听起来不错。 为什么每个人都没有这样做? 而且这个One-JAR似乎是从2004年开始出现的。为什么我们在这个市场上看不到更多参与者?

你知道他们说免费午餐吗? 没有了。 尽管这个概念非常简洁实用,但这并不意味着其他所有参与者都决定加入。因此,如果您的网站“需要”托管在大型付费应用程序服务器之一上(我不知道为什么您希望继续为那些了解它们的专有软件和技术人员付费。如果您不只是为高素质的技术人员付费,而是依赖那些不会让您陷入困境的开源应用程序,那么One-JAR对您来说可能不是一个可行的解决方案。 此外,我听到关于事情可能会变慢的不确定声音(如果您的应用很大,则在加载过程中。因此,在决定使用此功能之前,我建议您进行一次POC并确保您的技术堆栈中没有其他内容对One-JAR不满意。

我个人认为,2004年对于这种事情可能还为时过早。 人们仍然在为诸如构建和发布过程的标准化,在ORM领域获得明确的参与者,为MVC框架寻求明确的参与者等之类的问题而苦苦挣扎。这些问题还没有得到答案,或者很快就会出现。 但是我认为IT世界中当前问题的味道很普遍

  1. 如何使DevOps工作。
  2. 如何使整个构建和发布自动化。
  3. 如何利用开放源代码库提供可靠的软件,同时确保没有笨重的专有软件引起锁定,从而使解决方案的敏捷性降低,以适应未来的业务需求。

在我看来,One-JAR在该地区表现非常出色。 因此,我当然希望看到更多有关此工具和/或围绕此概念的更多工具。 而且,公平地说,该领域有更多参与者。 感谢Christian Schlichtherle指出了这一点。 有Maven Assembly Plugin和Maven Shade Plugin可以解决这个完全相同的问题。 我还没有尝试过它们,但是从文档上看,它们很不错,功能很明智。 Dropwizard ,虽然不是同一回事,但本质上非常相似。 他们通过嵌入式应用程序服务器扩展了整个jar的概念,对REST,JSON,Logback的开箱即用支持,以及一个很好的整洁包,您可以直接使用。

因此,正如我一直在说的那样,现在是从事技术业务的激动人心的时刻,尤其是如果您喜欢修补软件。

参考: Tech Jar for Enterprise博客上的Jjar合作伙伴 Partho可以对所有这些规则进行统治 。

翻译自: https://www.javacodegeeks.com/2013/01/one-jar-to-rule-them-all.html

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

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

相关文章

Django集合Ueditor

语言版本环境&#xff1a;python3.6 1、win安装步骤&#xff1a; 1 git下载源码https://github.com/zhangfisher/DjangoUeditor 2 解压DjangoUeditor3-master.tar 3 cd C:\Users\fj\Desktop\DjangoUeditor3-master 4 python setup.py install 官方建议使用pip install Djang…

计算机二级高级应用考题,2016计算机二级MSOFFICE高级应用考试真题

2016计算机二级MSOFFICE高级应用考试真题离2016上半年的计算机等级考试只有一个多月了&#xff0c;为了帮助大家尽快考试过关&#xff0c;小编整理了计算机二级office考试题&#xff0c;希望能帮助到大家!(1)下列叙述中正确的是A)一个算法的空间复杂度大&#xff0c;则其时间复…

ANTLR –语义谓词

用antlr解析简单的语法很简单 。 您要做的就是使用正则表达式描述您的语言&#xff0c;并让antlr生成词法分析器和解析器。 解析大型或复杂的语言有时会需要更多&#xff0c;因为仅使用正则表达式描述它们是困难的&#xff0c;甚至是不可能的。 语义谓词是在语法内部编写的Jav…

python输入一个数组输出24进制式的时间_4.4 用于数组的文件输入输出 线性代数...

Numpy能够读写磁盘上的文本数据或二进制数据。这一小节只讨论Numpy的内置二进制格式&#xff0c;因为更多的用户会使用pandas或其它工具加载文本或表格数据(见第6章)。np.save和np.load是读写磁盘数组数据的两个主要函数。默认情况下&#xff0c;数组是以未压缩的原始二进制格式…

DBMS-数据库设计与E-R模型:E-R模型、约束、E-R图、E-R扩展特性、E-R图转换为关系模式、UML建模...

设计过程概览 1. 设计阶段 最初阶段&#xff1a;刻画未来数据库用户的数据需求&#xff0c;产品为用户需求规格说明&#xff1b; 概念设计阶段&#xff08;conceptual-design phase&#xff09;&#xff1a;&#xff08;关注描述抽象数据及其联系&#xff0c;通常使用实体-联系…

tooltip.css-2.0文档

tooltip.css 纯CSS鼠标提示工具。 v. 2.0.0 更新日期&#xff1a;2018.4.12 预览DEMO。 安装&#xff1a; 只需在页面中引入"tooltip.css"或“tooltip.min.css”文件即可。 如&#xff1a; <link rel"stylesheet" href"css/tooltip.css"…

Java虚拟机:如何判定哪些对象可回收?

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请注明出处&#xff0c;欢迎交流学习&#xff01; 在堆内存中存放着Java程序中几乎所有的对象实例&#xff0c;堆内存的容量是有限的&#xff0c;Java虚拟机会对堆内存进行管理&#xff0c;回收已经“死去”的对象&…

html标签object和embed,html标签object和embed的区别

object和embed的区别The code in bold above is the actual code that you need to place in your page to embed a FusionCharts chart.In the above code, weveused and tags to embed the 3D Column Chart (Column3D.swf) within the HTML page.used &dataUrlData.xml u…

Apache Apollo REST API

Apache Apollo是新一代&#xff0c;高性能&#xff0c;多协议的消息传递代理&#xff0c;它是从头开始构建的&#xff0c;可以替代ActiveMQ5.x。 我过去曾在博客上发表过文章 &#xff08;第一部分已经与第二部分一起发布了&#xff09;。 Apollo的非阻塞异步体系结构使其速度…

bzoj1588 [HNOI2002]营业额统计

1588: [HNOI2002]营业额统计 Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 17931 Solved: 7391[Submit][Status][Discuss]Description 营业额统计 Tiger最近被公司升任为营业部经理&#xff0c;他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 T…

python管道通信_Python进程通信之匿名管道实例讲解

匿名管道管道是一个单向通道,有点类似共享内存缓存.管道有两端,包括输入端和输出端.对于一个进程的而言,它只能看到管道一端,即要么是输入端要么是输出端.os.pipe()返回2个文件描述符(r, w),表示可读的和可写的.示例代码如下:复制代码 代码如下:#!/usr/bin/pythonimport timeim…

css3中的box-sizing属性的使用

box-sizing属性用来定义元素的width和height所表示的区域,该属性一般有三种值&#xff1a;content-box、border-box、inherit。 其中inherit表示box-sizing的值应该从父元素继承。 content-box和border-box的主要区别就是元素的width和height的值包不包括border、padding这两…

ES6扩展运算符...进行的数组删除

今天写了按照React小书写了Reducer&#xff0c;发现基础真是太重要了&#xff0c;所有关于上层建筑的细节都需要回到下层细节中去寻找&#xff0c;而且现在的基础也由ES3变成了ES6了。 const ADD_USER "ADD_USER" const DELETE_USER "DELETE_USER" const…

中南大学在线考试答案计算机基础,中南大学《计算机基础》在线考试题库(267题)(有答案).doc...

中南大学《计算机基础》在线考试题库(267题)(有答案).doc 计算机基础01 总共89题共100分 一. 单选题 (共35题,共35分) 1. 域名服务器DNS的主要功能是( )。 (1分) A.通过请求及回答获取主机和网络相关的信息 B.查询主机的MAC地址 C.为主机自动命名 D.合理分配IP地址 ★标准答案&…

自动化的OSGi测试运行器

在我的团队成员中&#xff0c;我以忘记维护&#xff08;JUnit&#xff09;测试套件而闻名。 我只是无法为此付出额外的手动为套件添加测试的步骤。 幸运的是&#xff0c;有连续的集成服务器通过命名模式收集测试。 如果我介绍的一项孤立测试失败了&#xff0c;那么它会脱颖而出…

php post请求后端拿不到值_PHP Post获取不到非表单数据的问题解决办法

问题描述在使用vue-axios向后端post数据时&#xff0c;PHP端获取不到post的数据。问题解决修改php.ini配置找到php.ini配置文件&#xff0c;查找enable_post_data_reading变量&#xff0c;修改为打开状态&#xff0c;注释掉句前分好; Whether PHP will read the POST data.; Th…

CSS制作简单loading动画

曾经以为&#xff0c;loading的制作需要一些比较高深的web动画技术&#xff0c;后来发现大多数loading都可以用“障眼法”做出来。比如一个旋转的圆圈&#xff0c;并不都是将gif图放进去&#xff0c;有些就是画个静止图像&#xff0c;然后让它旋转就完了。gif图也可以&#xff…

机器学习:多变量线性回归

************************************** 注&#xff1a;本系列博客是博主学习Stanford大学 Andrew Ng 教授的《机器学习》课程笔记。博主深感学过课程后&#xff0c;不进行总结非常easy遗忘&#xff0c;依据课程加上自己对不明确问题的补充遂有此系列博客。本系列博客包含线性…

Java对象复活

总览 收集覆盖了finalize&#xff08;&#xff09;的对象之后&#xff0c;将其添加到终结处理队列中&#xff0c;以在调用每个对象的finalize&#xff08;&#xff09;方法之后进行清理。 如果您复活该物体&#xff0c;会发生什么&#xff1f; 何时定稿&#xff1f; finalize方…

经过路由无法找到计算机,电脑无法启动服务提示系统找不到指定的路径(图)

原标题&#xff1a;"电脑无法启动服务提示系统找不到指定的路径"相关电脑问题教程分享。 - 来源:191路由网。众所周知&#xff0c;使用电脑的时候需要启动一些服务才能使用相关的功能&#xff0c;但是如果出现无法启动服务项&#xff0c;并且提示“错误3&#xff1a;…