为什么将所有罐子组合在一起?

时间:2015-12-01 13:23:43

标签: java tomcat ant jar build

我已经基于JAX-RS创建了RESTful Web服务并使用了Jersey嵌入式Web服务器。我的ant脚本成功编译代码,而当我运行ClassNotFoundException时,它会给我错误main class。所以在做完研究之后我想出了解决方案&它来了java build ant file with external jar files。我做了什么创建了一个捆绑的jar文件尝试执行该&它工作得很好。我想知道背后的原因:

  • 为什么这个解决方案有效?
  • 为什么我要组合所有jar文件?

它类似于我们按照J2EE架构创建的war文件,否则战争将不会被服务器提取(比如说TOMCAT)&在我的情况下泽西嵌入式HTTP服务器的jar文件?

编辑: 这是我的蚂蚁build.xml文件

<property name="lib.dir" value="${user.dir}/lib"/>
<property name="build.dir" value="${user.dir}/build"/>
<property name="build.lib.dir" value="${build.dir}/lib"/>
<property name="build.classes.dir" value="${build.dir}/classes"/>
<property name="src.dir" value="${user.dir}/src/main/java"/>
<property name="main.class" value="com.assignment.ConsoleServer"/>

<path id="classpath">
    <fileset dir="${lib.dir}" includes="**/*.jar"/>
</path>

<target name="clean">
    <delete dir="${build.dir}"/>
</target>

<target name="init" depends="clean">
    <!-- Create the build directory structure used by compile -->
    <mkdir dir="${build.dir}"/>
    <mkdir dir="${build.classes.dir}"/>
</target>

<target name="copy_jars" depends="init" >
    <copy todir="${build.lib.dir}" >
        <fileset dir="${lib.dir}">
            <include name="**/*.jar" />
        </fileset>
    </copy>
</target>

<target name="compile" depends="copy_jars">

    <javac srcdir="${src.dir}" destdir="${build.classes.dir}" classpathref="classpath" includeantruntime="false"/>
</target>

<target name="jar" depends="compile">
    <jar destfile="${build.dir}/${ant.project.name}.jar" basedir="${build.classes.dir}">
        <manifest>
            <attribute name="Main-Class" value="${main.class}"/>
        </manifest>
        <zipgroupfileset dir="${lib.dir}" includes="*.jar"/>
    </jar>
</target>

<target name="run" depends="jar">
    <java fork="true" classname="${main.class}">
        <classpath>
            <path refid="classpath"/>
            <path location="${build.dir}/${ant.project.name}.jar"/>
        </classpath>
    </java>
</target>

这是我的文件夹结构

enter image description here

P.S。我不是java专家所以请原谅我,如果这个问题很愚蠢。

2 个答案:

答案 0 :(得分:0)

  

为什么这个解决方案有效?

在您的特定情况下,您可能没有在之前的部署中包含所有必需的依赖项。 (从您的问题中不清楚您最初是如何进行部署的。)

现在您已将所有应用程序和依赖类文件等放入一个JAR文件中,并且可能是您正在部署/运行该文件。它的工作原理是因为现在它拥有它需要运行的所有东西......它之前没有。

  

为什么我要组合所有jar文件?

在你的情况下,我怀疑这不是绝对必要的。可能有一种方法可以部署&#34;所有依赖项,而不将它们合并到一个JAR文件中。

然而,有一个案例是&#34; uber-jar&#34;有优势。那就是当JAR打算成为一个可执行的&#34; JAR,您希望能够将其作为单个文件进行分发/安装。 (和可执行的JAR 文件可以引用外部JAR等,但是你必须这样做 它是脆弱的&#34;。)

  

它与war文件类似吗??

排序,虽然WAR文件包含JAR文件......通常是Web容器理解的其他类型的资源。

答案 1 :(得分:0)

该解决方案有效,因为您将所有服务类和依赖库打包在一个jar中。该jar和内部的所有内容都将位于类路径中,并且对于执行虚拟机类加载器是可见的。 如果您将依赖的库放在外面,您的Jersey Web服务器需要将它们放在它的类路径上,那么您将无法获得ClassNotFoundExcpetion

您不应该在单个jar中打包Web应用程序。你应该把war文件放在哪里,你的依赖项放在WEB-INF / lib中。您可以轻松地在任何应用程序服务器上部署该战争。切换到Maven而不是Ant可以提供很多帮助。

编辑:在您向说明和蚂蚁

添加更多详细信息之后

如果你不想使用胖罐,你可以

  • 修改您的ant java任务以指定将引用的类路径 所有外部库(基本上告诉蚂蚁如何构建 -classpath命令
  • java -jar参数
  • 更好,通过制作正确指定javac的完整清单文件来修改您的Class-Path ant任务,做得更好 查看您链接的答案(java build ant file with external jar files
  • 的解决方案(位于底部)

关于Manifest here

的完整性参考