30

我从 C#/Visual Studio 背景来到 Java 和 Eclipse。在后者中,我通常会像这样组织一个解决方案:

\MyProjects\MyApp\MyAppsUtilities\LowerLevelStuff

其中 MyApp 将包含一个构建 .exe 的项目,MyAppsUtilities 将创建一个由 .exe 调用的程序集 DLL,而 LowerLevelStuff 可能会构建一个包含更高级别实用程序 DLL 使用的类的程序集。

在 Eclipse(Ganymede,但可能会被说服切换到 Galileo)中,我有:

\MyProjects\workspace\MyApp

当我创建我的初始项目时。可以选择将源文件和构建文件放在同一个文件夹中,但我在反映我的包层次结构的路径上创建了 .java 文件:

\MyProjects\workspace\MyApp\src\com\mycompany\myapp\MyApp.java

我的问题是:当我为 .jar 文件创建子项目(这是正确的 Java/Eclipse 术语吗?)这将类似于 .NET 中的上述 MyAppsUtilities 和 LowerLevelStuff 程序集 DLL 时,我可以(应该)等效地组织文件夹吗?例如:

\MyProjects\workspace\MyApp\src\com\mycompany\myapp\myapputilities\MyAppsUtilities.java

组织这些东西的标准/正确方法是什么,以及它是如何在 IDE 中具体完成的?

4

4 回答 4

60

将 Java 源代码包视为一个大的分层命名空间。商业应用程序通常位于“ com.mycompany.myapp ”下(此应用程序的网站可能是“ http://myapp.mycompany.com ”,但显然并非总是如此)。

如何在 myapp 包下组织内容很大程度上取决于您。您在 C# 中对可执行文件 (.exe)、DLL 和低级类所做的区分在 Java 中并不以相同的形式存在。所有 Java 源代码都被编译成 .class 文件(其内容称为“字节码”),这些文件可以在许多平台上由 Java 虚拟机 (JVM) 执行。因此,高级/低级类之间没有内在的区别,除非您通过包装对此类级别进行归因。一种常见的包装方式是:

  • com.mycompany.myapp:主类;MyApp(使用 main 方法)
  • com.mycompany.myapp.model:领域模型类;客户、订单等
  • com.mycompany.myapp.ui:用户界面(演示或视图)代码
  • com.mycompany.myapp.service:应用程序中的服务,即“业务逻辑”
  • com.mycompany.myapp.util:在多个地方使用的辅助类

这表明它是一个独立的 Java 应用程序,如果它是一个使用众多框架之一的 web 应用程序,它可能会有所不同。

这些包对应于项目中的目录层次结构。使用 Eclipse 时,这种层次结构的根称为“源目录”。一个项目可以定义多个源目录,通常是一个“主”和一个“测试”源目录。

项目中的文件示例:

src/test/java/com/acme/foo/BarTest.java
src/main/java/com/acme/foo/Bar.java
lib/utilities_1_0.jar

在实用程序_1_0.jar 中:

com/acme/foo/BarUtils.class

BarUtils.class 这是一个已编译的 java 类,因此采用独立于平台的字节码形式,可以在任何 JVM 上运行。通常 jarfile 仅包含已编译的类,尽管有时您可以下载还包含源 (.java) 文件的 jar 版本。如果您希望能够读取您正在使用的 jar 文件的原始源代码,这将非常有用。

在上面的 Bar 示例中,BarTest 和 BarUtils 都在同一个包 com.acme.foo 中,但物理上位于硬盘上的不同位置。

直接驻留在源目录中的类位于“默认包”中,将类保留在那里通常不是一个好主意,因为不清楚该类属于哪个公司和应用程序,如果有任何 jar 文件,您可能会遇到名称冲突你添加到你的类路径中包含一个在默认包中具有相同名称的类。

现在,如果您部署此应用程序,它通常会被编译成 .class 文件并捆绑在 .jar 中(这基本上是 .zip 文件加上一些清单信息的花哨名称)。制作 .jar 不是运行应用程序所必需的,但在部署/分发应用程序时很方便。使用清单信息,您可以使 .jar 文件“可执行”,以便用户可以轻松运行它,请参阅 [a]。

通常您还会使用多个库,即您从 Internet 获得的现有 .jar 文件。非常常见的示例是 log4j(一个日志框架)或用于访问数据库的 JDBC 库等。此外,您可能拥有自己的子模块,这些子模块部署在单独的 jarfile 中(如上面的“utilities_1_0.jar”)。如何在 jarfile 上拆分内容是部署/分发的问题,它们仍然共享 Java 源代码的通用命名空间。所以实际上,如果你愿意的话,你可以解压缩所有的 jar 文件并将内容放在一个大的目录结构中(但你通常不这样做)。

在运行使用/包含多个库的 Java 应用程序时,您会遇到通常称为“类路径地狱”的情况。正如我们所知,Java 的最大缺点之一。(注意:据说帮助正在路上)。要在命令行(即不是从 Eclipse)上运行 Java 应用程序,您必须在类路径中指定每个单独的 .jar 文件位置。当您使用 Java 的众多框架之一(Maven、Spring、OSGi、Gradle)时,通常会有某种形式的支持来减轻这种痛苦。如果您正在构建一个 Web 应用程序,您通常只需遵守其分层/部署约定,以便能够轻松地将事物部署到您选择的 Web 容器(Tomcat、Jetty、Glassfish)中。

我希望这能对 Java 中的工作原理有一些一般性的了解!

[a] 要制作 MyApp 应用程序的可执行 jar,您需要在路径上安装 JDK。然后在您的编译(bin 或目标)目录中使用以下命令行:

jar cvfe myapp.jar com.mycompany.myapp.MyApp com\mycompany\myapp

然后,您可以使用以下命令从命令行执行它:

java -jar myapp.jar

或者通过双击 jar 文件。请注意,在这种情况下您不会看到 Java 控制台,因此这仅对具有自己的 GUI(如 Swing 应用程序)或可能在后台运行(如套接字服务器)的应用程序有用。

于 2009-10-02T16:53:56.253 回答
11

Maven 有一个经过深思熟虑的标准目录布局。即使您不直接使用 Maven,您也可以将其视为事实上的标准。Maven“多模块”项目与您描述的 .net 多程序集布局非常相似。

于 2009-10-02T16:10:08.247 回答
2

通常,您会在 Eclipse 中将相关/子项目创建为不同的项目。

于 2009-10-02T15:36:23.307 回答
2

在回答这个问题之前,您需要澄清两件事:

  1. 您将使用哪个源代码存储库?
  2. 您将使用哪个构建系统在 Eclipse 之外自动构建工件?

答案将强烈影响您的选择。

我们选择了“一个 Eclipse 项目公关组件”,它可以是一个库,也可以是一个完成的可运行/可执行 jar。这使得使用 Hudson 轻松实现自动化。我们对 CVS 的使用也更容易,因为单个项目没有多重职责。

请注意,每个项目可能包含多个源文件夹,例如将测试代码与 Java 源的配置分开。这并不像简化你的结构那么重要。

于 2009-10-02T17:41:07.613 回答