![存钱罐小程序](https://i-blog.csdnimg.cn/blog_migrate/68c2de12acc011e8d84e3243e06b96f9.png)
存钱罐小程序
跳下内存通道
早在1998年,当我是一名C / C ++开发人员时,尝试使用Java时,有关该语言的一些内容对我来说就有点温和-令人讨厌。 我记得很担心这些
- 为什么没有合适的编辑器呢? C / C ++有很多。 我为Java拥有的只是旧的记事本。
- 当我想要的只是一个函数时,为什么我必须上一堂课? 为什么函数也不是对象?
- 为什么我不能将所有内容打包到一个zip / jar中,然后让最终用户双击启动?
和其他一些。 那时,我发现自己经常因为无法放弃自己的“ C / C ++思维方式”和拥抱“ Java方式”而自欺欺人。 现在,大约在十年半后的2013年写这篇文章,令人惊讶的是,所有这些早期烦恼都消失了。 不是因为我采用了“ Java”方式,而是因为Java发生了变化。
除了闲聊,本文的重点是谈论这些问题之一–“为什么我不能只将所有内容打包到一个zip / jar中,让最终用户双击启动?”。
为什么我们需要一个可执行的zip / jar文件?
如果您是一名开发人员,请在您的IDE上进行愉快的编码(我鄙视所有从一开始就在Eclipse上进行过Java编码的人,从一开始就不必在NetBeans上进行编写而不必在记事本上进行编码的人),以及Google的帮助(我非常讨厌所有人(他们不必在Google之前就可以在互联网上找到东西),可能没有令人信服的案例。
但是,当您遇到一种情况时
- 您之所以进入数据中心,是因为那里的人遵循了您的部署步骤,但是您的应用程序/网站根本无法正常工作?
- 突然之间,当“根本没有人碰到”生产箱时,环境变量全部搞砸了,而您就是必须“使其正常工作”的人。
- 您正与业务利益相关者坐在一起,难以置信地盯着“ 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上进行更新,没人认为会影响您的jar。 我们可以讨论和辩论多种方法来阻止此类不幸事件,但是最重要的是x.jar(开发人员责任)具有依赖性(开发人员不直接控制)。 这会导致不幸。
当然,如果将由于不同版本,不同应用程序服务器等导致的全部变量添加到此混合中,那么仅提供x.jar的现有解决方案很快就会显得非常脆弱。
那么我们该怎么办?
对P. Simon Tuffs博士表示感谢。 这位先生在此环节解释了他如何迎合这个问题。 这是一本好书,我推荐。 我用非常普通的话解释过的(几乎没有刮过表面),西蒙深入研究了该问题及其解决方法。 长话短说,他编写了一个解决方案并将其开源。 我将不再重播相同的信息-阅读他的文章,内容非常丰富-但我将指出他解决方案的重点。
- 它使人们可以创建一个包含所有内容(包括代码,资源,依赖项,应用程序服务器(可能))的jar。
- 它允许最终用户通过简单的java -jar jarFileName命令来运行整个humongous jar。
- 它允许开发人员以与开发相同的方式进行开发,例如,如果它是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世界当前存在各种问题
- 如何使DevOps工作。
- 如何使整个构建和发布自动化。
- 如何利用开放源代码库提供可靠的软件,同时确保没有笨重的专有软件引起锁定,从而使解决方案的敏捷性降低,以适应未来的业务需求。
在我看来,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
存钱罐小程序