2

- - - - -编辑 - - -

所以我现在意识到我的错误源于命令行启动,而不是通过单击它们来启动 jar。本质上,如果我从任何文件夹运行 jar,但它们实际驻留在的文件夹中,那么我的资源被错误地引用。如果我从同一个文件夹执行命令行,这个问题就会消失。所以问题变成了我可以做些什么来相对引用 jar 和资源,而不管从哪里调用执行?

- - - - 编辑 - - -

我在尝试构建一个用于分发的项目时遇到了几个问题。项目结构是这样的,我有 6 个包。每个包分为两个子包 Gui 和 Engine。每个子包都有一个可运行的主类。“Common”包是其他包的包装器,并启动任何被选中的包。我的目标是将每个包打包成独立的,用于引擎方面。这用于引擎的命令行测试。“Common” jar 与所有资源放在一起并运行整个应用程序。

我的问题源于需要清理项目。所以重构和重新打包正在进行,但是目前用于构建和 jar 项目的方法是一个批处理脚本,它将类文件(考虑包/文件夹结构)复制到最终文件夹位置。从那里创建 jars 命令行,并在清单文件中概述类路径和主类。这工作得很好,罐子用正确的结构和类路径编译,一切运行正常。然而,保持 xcopy 命令正确是一件很痛苦的事情,因为它需要更改为包结构更改为的任何内容,以及取决于谁在构建项目的位置。

所以我的解决方案是为 netbeans 使用 build.xml 和大纲 ant 构建。这将尊重任何项目结构更改并将构建保留在 netbeans 内部。我遇到的确切问题是,无论使用哪种构建方法。(批处理/构建脚本)我使用任何一种方法都可以在 jar 中获得确切的文件夹结构,并且类路径完全相同。我的 common.jar 适用于该项目,但我的引擎测试 jar 遇到类路径或参考问题。我将包含大部分 ant 脚本、批处理文件和使用的清单文件。

批处理文件

xcopy /Y C:\Users\tfollansbee\Documents\NetBeansProjects\Emerson\branches\Merge\build\classes\Common  C:\Emerson\Common\
xcopy /Y C:\Users\tfollansbee\Documents\NetBeansProjects\Emerson\branches\Merge\build\classes\Common\gui C:\Emerson\Common\gui\
xcopy /Y C:\Users\tfollansbee\Documents\NetBeansProjects\Emerson\branches\Merge\build\classes\Common\Meg C:\Emerson\Common\Meg\

xcopy /Y C:\Users\tfollansbee\Documents\NetBeansProjects\Emerson\branches\Merge\build\classes\Pressu re C:\Emerson\Pressure\
xcopy /Y  C:\Users\tfollansbee\Documents\NetBeansProjects\Emerson\branches\Merge\build\classes\Pressure\Gui C:\Emerson\Pressure\Gui\
xcopy /Y  C:\Users\tfollansbee\Documents\NetBeansProjects\Emerson\branches\Merge\build\classes\Pressure\Meg C:\Emerson\Pressure\Meg\

xcopy /Y C:\Users\tfollansbee\Documents\NetBeansProjects\Emerson\branches\Merge\build\classes\PressureV2 C:\Emerson\PressureV2\
xcopy /Y C:\Users\tfollansbee\Documents\NetBeansProjects\Emerson\branches\Merge\build\classes\PressureV2\Gui C:\Emerson\PressureV2\Gui\
xcopy /Y C:\Users\tfollansbee\Documents\NetBeansProjects\Emerson\branches\Merge\build\classes\PressureV2\Gui\controller C:\Emerson\PressureV2\Gui\controller
xcopy /Y C:\Users\tfollansbee\Documents\NetBeansProjects\Emerson\branches\Merge\build\classes\PressureV2\Gui\models C:\Emerson\PressureV2\Gui\models
xcopy /Y C:\Users\tfollansbee\Documents\NetBeansProjects\Emerson\branches\Merge\build\classes\PressureV2\Gui\rules C:\Emerson\PressureV2\Gui\rules

xcopy /Y C:\Users\tfollansbee\Documents\NetBeansProjects\Emerson\branches\Merge\build\classes\Temp\Gui C:\Emerson\Temp\Gui\
xcopy /Y C:\Users\tfollansbee\Documents\NetBeansProjects\Emerson\branches\Merge\build\classes\Temp\Meg C:\Emerson\Temp\Meg\

xcopy /Y C:\Users\tfollansbee\Documents\NetBeansProjects\Emerson\branches\Merge\build\classes\rfdFlow\Gui C:\Emerson\rfdFlow\Gui\
xcopy /Y C:\Users\tfollansbee\Documents\NetBeansProjects\Emerson\branches\Merge\build\classes\rfdFlow\Meg C:\Emerson\rfdFlow\Meg\

xcopy /Y C:\Users\tfollansbee\Documents\NetBeansProjects\Emerson\branches\Merge\build\classes\utils C:\Emerson\utils\

"C:\Program Files\Java\jdk1.6.0_25\bin\jar" cvmf mainClass tempAsynch.jar Temp/*
"C:\Program Files\Java\jdk1.6.0_25\bin\jar" cvmf mainClass Common.jar Common/*
"C:\Program Files\Java\jdk1.6.0_25\bin\jar" cvmf pressureClass Pressure.jar Pressure/*
"C:\Program Files\Java\jdk1.6.0_25\bin\jar" cvmf pressureV2Class PressureV2.jar  PressureV2/*
"C:\Program Files\Java\jdk1.6.0_25\bin\jar" cvmf rfdClass rfdFlow.jar rfdFlow/*
"C:\Program Files\Java\jdk1.6.0_25\bin\jar" cvmf pressureV2Class utils.jar utils/*

rmdir /s /q C:\Emerson\Common
rmdir /s /q C:\Emerson\Pressure
rmdir /s /q C:\Emerson\PressureV2
rmdir /s /q C:\Emerson\Temp
rmdir /s /q C:\Emerson\rfdFlow
rmdir /s /q C:\Emerson\utils

xcopy /Y C:\Emerson\Common.jar C:\GCCDEV
xcopy /Y C:\Emerson\tempAsynch.jar C:\GCCDEV
xcopy /Y C:\Emerson\Pressure.jar C:\GCCDEV
xcopy /Y C:\Emerson\PressureV2.jar C:\GCCDEV
xcopy /Y C:\Emerson\rfdFlow.jar C:\GCCDEV
xcopy /Y C:\Emerson\utils.jar C:\GCCDEV

构建脚本

<?xml version="1.0" encoding="UTF-8"?>
<project name="Emerson" default="default" basedir=".">
<description>Builds, tests, and runs the project Emerson.</description>
<property environment="env"/>
<property name="baseDir" value="build/classes/" />
<property name="cp" value=" . utils.jar lib/pfcasync.jar lib/poi-3.7/poi-ooxml-schemas-3.7-20101029.jar lib/poi-3.7/poi-3.7-20101029.jar lib/poi-3.7/poi-ooxml-3.7-20101029.jar lib/poi-3.7/ooxml-lib/xmlbeans-2.3.0.jar lib/poi-3.7/ooxml-lib/dom4j-1.6.1.jar lib/xom/xom-1.2.7.jar lib/jgoodies/jgoodies-common-1.3.0.jar lib/jgoodies/jgoodies-binding-2.6.0.jar lib/resources/** Common.jar 
" />
<import file="nbproject/build-impl.xml"/>
<target name="-pre-jar">
    <echo message="-pre-jar" />
    <delete dir="${env.PTC_STD}/lib/" />
    <delete dir="${env.PTC_STD}/resources/" />
    <!--delete dir="${env.PTC_STD}/build/" /-->
    <echo message="aJar" />
    <jar destfile="${env.PTC_STD}/Common.jar" basedir="${baseDir}">
        <manifest>
            <attribute name="Class-Path" value="${cp}" />
            <attribute name="Main-Class" value="Common.gui.emersonWrapper" />
        </manifest>
    </jar>
    <jar destfile="${env.PTC_STD}/tempAsynch.jar" index="false" basedir="${baseDir}" includes="Temp/**">
        <manifest>
            <attribute name="Class-Path" value="${cp}" />
            <attribute name="Main-Class" value="Temp.Meg.tempasynch" />
        </manifest>
    </jar>
    <jar destfile="${env.PTC_STD}/Pressure.jar" index="false" basedir="${baseDir}" includes="Pressure/**">
        <manifest>
            <attribute name="Class-Path" value="${cp}" />
            <attribute name="Main-Class" value="Pressure.Meg.P3051STest" />
        </manifest>
    </jar>
    <jar destfile="${env.PTC_STD}/PressureV2.jar" index="false">
        <fileset dir="${baseDir}">
            <include name="PressureV2/**" />
            <include name="utils/**" />
        </fileset>
        <manifest>
            <attribute name="Class-Path" value="${cp}" />
            <attribute name="Main-Class" value="PressureV2.Gui.PressureV2Main" />
        </manifest>
    </jar>
    <jar destfile="${env.PTC_STD}/rfdFlow.jar" index="false" basedir="${baseDir}" includes="rfdFlow/**">
        <manifest>
            <attribute name="Main-Class" value="rfdFlow.Meg.main" />
            <attribute name="Class-Path" value="${cp}" />
        </manifest>
    </jar>
    <jar destfile="${env.PTC_STD}/utils.jar" index="false" basedir="build/classes/" includes="utils/**">
        <manifest>
            <attribute name="Class-Path" value="${cp}" />
            <attribute name="Main-Class" value="PressureV2.Gui.PressureV2Main" />
        </manifest>
    </jar>
    <copy todir="C:/Emerson/resources/">
        <fileset dir="resources/">
            <exclude name="**/*.svn"/>
        </fileset>
    </copy>
    <copy todir="C:/Emerson/lib/">
        <fileset dir="lib/">
            <include name="**/*.jar" />
            <include name="**/resources/**" />
        </fileset>
    </copy>
</target>
</project>

常见的清单文件。包含的类路径在所有其他清单文件中完全相同

Main-Class: Common.gui.emersonWrapper
Class-Path: . utils.jar lib/pfcasync.jar lib/poi-3.7/poi-ooxml-schemas-3.7-20101029.jar lib/poi-3.7/poi-3.7-20101029.jar lib/poi-3.7/poi-ooxml-3.7-20101029.jar lib/poi-3.7/ooxml-lib/xmlbeans-2.3.0.jar lib/poi-3.7/ooxml-lib/dom4j-1.6.1.jar lib/xom/xom-1.2.7.jar lib/jgoodies/jgoodies-common-1.3.0.jar lib/jgoodies/jgoodies-binding-2.6.0.jar lib/resources/** Common.jar

在运行时,jar 都存在于同一个文件夹中,以及一个包含所有引用库 jar 的“lib”文件夹。连同一些图像和一些 xml 数据。我在创建 jar 时注意到的一个区别是批处理文件没有创建索引。最初在我的 ant 脚本中,我有 index="true",当运行例如 pressure.jar 时,我会得到一个 java.lang.NoClassDefFoundError。我设置了 index="false" 并且我的这些错误消失了,但是在 lib/resources/xml/a.xml 中找不到我的相对路径 xml 文件。所有这一切的真正关键是构建方法之间的差异。我花了两天时间研究了 jar 结构、文件夹结构和类路径。在 build.xml 中,我什至链接到批处理文件中使用的清单文件,但没有成功。一切都一样,所以为什么这些罐子在运行时的行为方式有所不同。我觉得我错过了一个小细节。

4

1 回答 1

0

不完全清楚你的问题是什么,所以这是我的观察:

管理 jar 类路径清单条目

以下答案演示了如何使用 ANT manifestclasspath任务在可执行 jar 清单中动态构建“Class-Path”属性:

Ant - 如何在特定文件夹中获取所有文件的名称

管理第 3 方依赖项

如果您的构建管理大量开源 jar,请考虑使用Apache ivy插件自动为您下载它们。

你可以做得更好,部署一个像Nexus这样的专用存储库管理器来托管你所有的构建依赖项。

于 2012-04-25T17:42:21.607 回答