- - - - -编辑 - - -
所以我现在意识到我的错误源于命令行启动,而不是通过单击它们来启动 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 中,我什至链接到批处理文件中使用的清单文件,但没有成功。一切都一样,所以为什么这些罐子在运行时的行为方式有所不同。我觉得我错过了一个小细节。