如何让Netbeans自动将第三方jar包从一个包含的类库复制到我的项目的dist/lib目录?

14

我在NetBeans 7.1中有一个Java应用程序(我们称之为myApp),它依赖于一个Java类库项目 [实际上不止一个],其中我保存了一些在项目之间共享的实用类。

这个类库项目(我们称之为myLib)依赖于[很多]第三方库(例如apache-commons-younameit.jar)。

我将myLib作为库包含进来,NetBeans的Ant脚本将myLib.jar拉入我的myApp项目的 dist/lib 目录;但是,myLib所依赖的jar文件并没有与myLib一起被拉入,因此我的项目由于缺少apache-commons-youtnameit.jar而产生运行时异常。

我希望同时自动拉取myLib.jar和apache-commons-younameit.jar到myApp的dist/lib文件夹中,这样我就不必手动检查所有库的依赖项并将它们添加到我的主项目中。

  • 是否有通过NetBeans对话框明显实现此功能的方法?
  • 或者是否需要手动调整我的build.xml?如果是,请您提供一个示例?(我对Ant不是很熟悉)

我希望避免以下操作:

  1. 我需要添加一个新的实用库,从我的Java类库项目中选择。
  2. 我查找该库中使用的库,并将它们写下来。
  3. 我回到我的主项目,并添加这些第三方库(仅添加我尚未直接在我的主项目中使用的库)。

预先感谢您的任何帮助或指导。


如果您能将jar文件放入项目的jar文件中,那么您将使用什么程序来读取这些内部jar文件呢? 我认为java命令不知道如何从包含在jar文件中的jar文件中读取。 - Rakesh
@Rakesh 你好,我不需要在项目jar包中获取jars文件:我只想将项目依赖的依赖项中的jars文件复制到项目的“lib”文件夹中。 - Unai Vivi
1
你不会错过任何东西。在NetBeans项目中,您无法使用向导或属性对话框完成此操作。我建议学习Maven,NetBeans Maven项目可以满足您的所有要求。 - Saeed Zarinfam
1
@UnaiVivi 我也遇到了同样的问题。你解决了吗? - horgh
1
@horgh 很抱歉,我还没有找到解决方案。目前仍在手动跟踪库...如果我找到了解决方案,我会在这里发布的,请保持关注。谢谢。 - Unai Vivi
5个回答

10

我在您的评论中找到了一种复制“依赖库所依赖的库”的方法,希望这能有所帮助。

<import file="nbproject/build-impl.xml"/>行后,在NetBean项目的build.xml文件中添加以下代码。你需要在下面的<fileset>标签中填写正确的相对路径。

<!--Copy over any "dependant libraries' dependant libraries" -->
<target name="-post-jar">
    <echo>Copying over extra jars into PROJECTNAME</echo>
    <copy todir="./dist/lib">
        <!-- put in order from least important to most important to prevent file overwrites -->
        <fileset dir="path-to-other-nb-project/dist/lib"></fileset>
        <fileset dir="path-to-second-nb-project/dist/lib"></fileset>
    </copy>
</target>

虽然代码不是很规范,但对我来说解决了问题。当您将额外的依赖项目添加到主项目中时,您需要手动更新它。


5
这是我在Netbeans 7.3中的解决方法:
右键单击您的项目,选择“属性”,然后在右侧选择“库”。
然后在“库文件夹”下点击“浏览”按钮: Properties dialog 然后选择您的lib文件夹,除非Netbeans已经自动选择了它: Add Libraries Folder dialog 然后根据需要单击“下一步”,“完成”,回到“属性”对话框后,您应该看到: Properties dialog final Setup 之后,Netbeans会将lib文件夹复制到dest,并最重要的是会在您的主JAR的MANIFEST.MF文件中引用所有库。
作为测试,请查看lib文件夹中是否有一个新的CopyLibs文件夹。在CopyLibs文件夹中应该有一个org-netbeans-modules-java-j2seproject-copylibstask.jar文件。Netbeans添加了这些文件,我认为这是驱动将lib文件夹复制到dist的原因。

3

我曾经遇到同样的问题,然后我写了一个ant任务来自动复制所有包含在类库项目中的依赖库到我的主项目中。这个方法不需要包含任何第三方库。

在类库项目选项中设置 Copy Dependent Libraries 复选框以使其生效。然后Netbeans会将所有依赖库复制到类库项目的 dist/lib 文件夹中,与 Gregory 的解决方案 类似。这种方法的优点是,当你向主项目中添加更多的类库时,你无需每次都修改你的 build.xml 文件。

工作原理

我的 ant 任务首先会在主项目属性中搜索所有包含的项目的路径,然后打开它们的 project.properties 文件,读取类库项目的 dist 文件夹并将所有库复制到 dist 文件夹的 lib 目录下。

还有一个测试来判断是否启用了 Copy Dependent Libraries

代码

位于项目父文件夹中的 build-import-libraries.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
 <!--
      Custom import of libraries.
      This is not done in Netbeans, because the dist folder is created at runtime.

      To work correctly, disable the compile on save feature for your project.

      Author: Christophe Weis
 -->
<project name="IncludeLibraries" default="default" basedir=".">
    <description>Includes dependent libraries in projects using class-library projects.</description>
    <dirname property="IncludeLibraries.basedir" file="${ant.file.IncludeLibraries}"/>
    <target name="copy-files">
        <!-- Set variable to the folder where to copy the files to -->
        <condition property="libdestdir" value="${build.web.dir}/WEB-INF/lib" else="${dist.dir}/lib">
            <isset property="build.web.dir"/>
        </condition>
        <echo message="Custom build step in file '${ant.file}': copying dependent libraries from included Netbeans projects to '${libdestdir}'" level="info"/>
        <echo message="Please make sure that 'Copy Dependent Libraries' is enabled in Netbeans project options for each included project" level="info"/>
        <copy-dependent-libs>
            <propertyset id="properties-starting-with-project">
                <propertyref prefix="project."/>
            </propertyset>
        </copy-dependent-libs>
    </target> <!-- End custom import -->

    <scriptdef name="copy-dependent-libs" language="javascript">
        <element name="propertyset" type="propertyset"/>
        <![CDATA[
            // Ant uses the Rhino JavaScript implementation

            propertySets = elements.get("propertyset");
            // loop all nested property sets
            for (i = 0; i < propertySets.size(); ++i) {
                propertySet = propertySets.get(i);
                properties = propertySet.getProperties();
                for (var iterator = properties.entrySet().iterator(); iterator.hasNext();) {
                    var entry = iterator.next();
                    var key = entry.getKey();
                    if ("project.licensePath".equals(key)) {
                        continue;
                    }
                    var value = entry.getValue();

                    // read the referenced project's property file
                    var file = new java.io.File(project.getBaseDir(), value + "/nbproject/project.properties");
                    var inputStream = new java.io.FileInputStream(file);
                    var projectProperties = new java.util.Properties();
                    projectProperties.load(inputStream);
                    inputStream.close();
                    var distFolder = projectProperties.getProperty("dist.dir");

                    // check if 'Copy Dependent Libraries' is enabled
                    var doNotCopyDependentLibraries = projectProperties.getProperty("mkdist.disabled");
                    doNotCopyDependentLibraries = java.lang.Boolean.parseBoolean(doNotCopyDependentLibraries);
                    if (doNotCopyDependentLibraries) {
                        self.fail("Please enable 'Copy Dependent Libraries' in project properties for project " + projectProperties.getProperty("application.title", value));
                    }

                    t = project.createTask("copy-files-from-libfolder");
                    // set the dist folder's lib directory
                    t.setDynamicAttribute("fromdir", value + "/" + distFolder + "/lib");
                    t.perform();
                }
            }
        ]]>
    </scriptdef>

    <macrodef name="copy-files-from-libfolder">
        <attribute name="fromdir" />
        <sequential>
            <echo message="Copying libraries from directory '@{fromdir}' to '${libdestdir}'" level="verbose" />
            <copy todir="${libdestdir}">
                <fileset dir="@{fromdir}">
                    <!-- Enable this if you wish
                    <exclude name="servlet-api.jar"/>
                    -->
                </fileset>
            </copy>
        </sequential>
    </macrodef>

</project>

<import file="nbproject/build-impl.xml"/>后面,在build.xml文件中加入以下行(您可能需要在导入任务中适应build-import-libraries.xml的路径):
<!-- 
     Custom import of libraries.
-->
<import file="../build-import-libraries.xml" as="include-libraries" />
<target name="-post-compile" depends="include-libraries.copy-files" />

这适用于Java SE应用程序和Java Web应用程序。我只在Netbeans 8.0.2版本中测试过。希望这在未来的版本中仍然有效。


非常优雅和有效的解决方案。 - Unai Vivi
谢谢!顺便说一下,我只在“build-import-libraries.xml”的最后一个“copy”任务中添加了“failonerror =” false“。否则,对于没有依赖项的依赖项,脚本将失败 :) - georges abitbol

1
李的答案适用于NetBeans 7.2中的Java应用程序项目。如果您想在NetBeans中使用Maven,则必须创建一个Maven Java应用程序项目。修改pom.xml文件以包含maven assembly plugin
<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>2.4</version>
    <configuration>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        <archive>
            <manifest>
                <mainClass>your.app.MainClass</mainClass>
            </manifest>
        </archive>
    </configuration>
    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

不,我不使用Maven:我使用Ant。 - Unai Vivi
这对于使用ant的用户来说可能没有用,但是对于maven来说它非常好用。 - Juan Carlos

0
假设您已将它们全部添加到项目类路径下(在项目属性中的下)。您可以进入构建 > 打包并勾选复制依赖库
我正在使用Netbeans 7.2。

1
它复制依赖库,并且这个选项已经将库JAR复制到dist文件夹;我需要做的是复制依赖库的依赖库,而这个选项不会这样做(不幸的是)... - Unai Vivi
此外,当您从命令行Ant(例如在Jenkins构建中)调用构建时,该选项似乎被忽略了。 - npskirk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接