当前位置: 首页 > 知识库问答 >
问题:

编译和运行java项目与许多依赖类在其他目录

上官恩
2023-03-14

我有我所有目录的结构:

我正在尝试编译和执行ServerMain和ClientMain。以下编译工作:

src>javac -cp .;../lib/gson-2.8.2.jar client/gui/*.java client/net/*.java client/*.java server/*.java server/net/*.java server/exceptions/*.java server/controller/*.java server/data/*.java common/*.java

我必须不在src中执行程序,而是在前一个目录中执行,因为在代码中有一个从cfg目录中的配置文件读取的函数。

我试图执行这个命令,但我有很多错误:ClassesNotFound或cfg文件路径中的错误(代码中是/cfg/server.cfg)或ServerMain未找到。

以下命令在图像中项目的src的上一个目录中执行

java -cp lib/gson-2.8.2.jar src/server/WinsomeServerMain

我如何正确执行?

共有1个答案

江育
2023-03-14

唯一真正正确的答案是:把所有这些东西都扔进垃圾箱;去给自己找一个构建系统,比如maven或gradle。

javac并不擅长在不同的目录中编译许多相互关联的源文件,然而,仅仅将所有代码集中到一个巨大的包中并不是一个好主意。这些工具非常有用。你只是。。告诉他们编译。他们知道java源代码在 SRC/Ma/java java/代码>,并且可以很容易地调整,以考虑2个单独的“项目”(<代码> SRC/Client/java < /Cube >和 Src/Server /Java<代码> >,在您的情况下),甚至为这些提供单独的JAR。

还有一个依赖管理的问题:有了这些工具,你只需要在配置文件中写一个所谓的GAV字符串(组/工件/版本),比如com.google.gson::gson::2.9.0,maven/gradle就可以处理它。它知道在哪里可以在线找到gson并为你下载,并确保它自动出现在所有相关的类路径上。这很好:在你的源代码控制系统中粘贴所有这些dep意味着源代码控制大小飙升,这很烦人,所以如果不在源代码控制中,你如何在计算机/开发人员之间传输gson?答案是:你不需要——每个需要它的系统都自动下载它。maven和gradle可以为你做这件事。

最后,你可以免费获得“只编译所有文件”,你不需要像现在这样列出6个目录。这很好。

你错了。但如果你必须:

您的javac命令将所有各种文件编译到位,这意味着您现在拥有了。在包含src的文件夹结构中初始化文件,现在你的项目结构对你撒谎了。这没用。如果你真的想让java和类文件生活在同一个目录中,那就去掉层次结构中的src。然后就变成了yourMainProjectDir/client/net/MyClient。java和它旁边的MyClient。类。或者,使用-d开关告诉javac输出到特定目录。例如,bin

javac -d bin -cp 'lib/*' client/gui/*.java ..and all other dirs here..

java不运行文件。它运行类。顺序参数(在您的示例中是src/server/Winsome ServerMain)是一个完全限定的类名。类似于java.lang.String,而不是java/lang/String.classjava将扫描类路径中列出的每个目录(这些目录是ARE文件/目录,并以-cp传递)。

在你的例子中,类路径上需要两个独立的东西:gson和你自己的类文件,你刚刚编译了它们。

因此:

java -cp 'lib/*:bin' server.WinsomeServerMain

这里发生了一些事情:

>

  • 我不知道你的包裹是什么,你的问题不清楚。你应该有一个包xyz语句。java文件。如果是服务器,则上面的说明是“正确的”。如果没有package语句,您需要一个packageless语句,它对所有东西都是不可见的,除了它自己的包中的其他东西,并且在引入任何类型的层次结构时都应该放弃它。

    Java可以在类路径中处理*,但必须让Java来解包。在除了普通的jane windows之外的几乎所有shell环境中,shell都会看到*并为您解包,您不希望看到,因此,您必须使用单引号来告诉shell不要对其进行操作。而且,java非常简单,只理解*。它不理解*。jar,所以不要键入它。类路径根包含类路径。因此,bin是根目录(因为类文件直接在其中),而lib不是根目录(因为类文件不在lib中——它们在jar文件中,jar文件在lib中)。因此,这不是打字错误:bin单独列出,而是lib/*。这意味着你可以在lib中放入你想要的任何库,lib/*将获得它们。

    如果这些配置文件是只读的(“随应用程序一起提供”——永远不会更改并且在编译时知道的静态数据),那么应该将它们粘贴到jar文件中,并使用getResourceAsStream读取它们。如果它们是用户可配置的,那么它们不应该与类文件一起使用——类文件是代码,代码应该以最佳方式放置在只读位置(至少就代码而言)。这就是为什么将可编辑文件粘贴在它们旁边是个坏主意。

    一个好的解决方案是在jar中发送模板版本(使用YourClass.class.getResourceAsStream("/configtemplate.txt")读取它们-如果文件在jar的根中,它将找到该文件。开始时,读取Paths.get(System.get属性("user.home "), " myapp.config"),如果缺少,创建它,用模板填充它,并告诉用户去编辑它。

    写入用户的主目录(Windows上的C:\User\YourUserName,linux上的 /home/youracct,mac上的 /Users/youracct等),用于此目的,并且绝对是可写的。

    构建系统的另一个优点是它们使创建好的部署变得更容易:你真的希望你的文件在一个指定自己类路径的jar文件中。构建工具可以做到这一点。你最好“运送”你的应用程序,这样某人最终会得到:

    C:\Program Files\YourApp\YourApp.jar
    C:\Program Files\YourApp\lib\gson.jar
    

    运行应用程序所需的唯一一件事就是键入java-jar-YourApp。jar或者双击你的应用程序。jar在浏览器中——尽管所有这些都与平台无关(在windows和Mac上也是如此)。您可以这样做——jar可以指定自己的类路径,该类路径是相对于jar解析的。这涉及到包含一个清单,其中包含key类路径:lib/gson。罐子在里面。你可以手工操作(jar-cvmf-MyManifest.mf-MyApp.jar-client/ui/*.class-client/*.class-etcetera——类似的东西,在这里你可以创建MyManifest.mf文本文件并列出其中的键),但是这里有很多步骤,gradle/maven可以自动完成。

  •  类似资料:
    • 我的Servlet源代码是: 我使用tomcat作为Web服务器,只是一个文本编辑器(Atom)来帮助我完成这个挑战(现在是stackoverflow)。我现在的问题是编译器没有找到我已经编译的类计算机,但没有成功修复这个错误。

    • 我有一个多项目gradle项目,结构如下。 从顶层“Project A”运行Gradle任务时,一切都正常工作 但是,当我尝试在子项目(如“subproject C”)上运行单个任务时,会出现以下错误。 失败:构建失败,但有一个异常 出了什么问题: 评估根项目“SubProject C”时出现问题。 在根项目“SubProject C”中找不到带有路径“: Shared”的项目。 我想我看到了问题

    • 我有两个Maven(GWT)项目,其中一个应该依赖于另一个。我只是添加了依赖项,比如: 这些类被正确引用,我可以在我的其他项目中使用它们。但如果我想触发maven构建,它会抱怨:“无法解析项目的依赖项:找不到工件myGroup:MyArtifact:jar:1.0-SNAPSHOT” 该项目没有jar,因为它是一个GWT Web应用程序。它有一个“战争”档案。我测试了一下论点,尝试了“pom”或“

    • 我需要使用WebSocket,但是我们使用的旧版本的PHP不支持它们。我决定尝试一个Java的WebSocket服务器。我已经在Android Studio中编写了一些Android应用程序,所以我熟悉Java的基本语法,但是几乎没有手动编译和运行java的经验。 我希望服务器是一个单一的文件,我可以从命令行运行一次,然后忘记它。为此,我决定使用这个库,在示例中包含一个Javascript聊天应用

    • 在之前提到的多项目配置中,:libraries:lib1 和 :libraries:lib2 可以是 Java 项目,并且 :app 这个 Android 项目将会使用它们输出的 jar 包。然而,如果你想这部分代码能够访问 Android APIs 或者使用 Android 的资源,那么这些 Library 项目就不能是 Java 项目,只能是 Android Library 项目。

    • 我已经在NetBeans8.1中创建了5个不同的Java SE项目。我想创建一个新的项目,该项目带有一个介绍窗口,该窗口带有链接/打开链接到该按钮的项目的按钮,并从该窗口创建一个软件。 我已经在主项目->Properties->Library->Compile->Add Project中添加了依赖项(其他项目的jar文件)。 当我在netbeans中运行它们时,运行窗口打开了,但是当我从主项目中调