Eclipse Java project folder organization

2019-01-16 04:50发布

问题:

I am coming to Java and Eclipse from a C#/Visual Studio background. In the latter, I would normally organize a solution like so:

\MyProjects\MyApp\MyAppsUtilities\LowerLevelStuff

where MyApp would contain a project to build a .exe, MyAppsUtilities would make an assembly DLL called by the .exe, and LowerLevelStuff would probably build an assembly containing classes used by the higher-level utilities DLL.

In Eclipse (Ganymede, but could be convinced to switch to Galileo) I have:

\MyProjects\workspace\MyApp

When I create my initial project. There is an option to put source and build files in same folder, but I have .java files created on a path that is reflective of my package hierarchy:

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

My question is this: when I create subprojects (is that the right Java/Eclipse term?) for .jar files that will be analogous to the above MyAppsUtilities and LowerLevelStuff assembly DLLs in .NET, can (should) I organize the folders equivalently? E.g.:

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

What is the standard/right way to organize this stuff, and how is it specifcally done in the IDE?

回答1:

Think of Java source code packages as one big hierarchical namespace. Commercial applications typically live under 'com.mycompany.myapp' (the website for this application might be 'http://myapp.mycompany.com' although this is obviously not always the case).

How you organize stuff under your myapp package is largely up to you. The distinction you make for C# between executable (.exe), DLL's and low-level classes does not exist in the same form in Java. All Java source code is compiled into .class files (the contents of which is called 'bytecode') which can be executed by a Java Virtual Machine (JVM) on many platforms. So there is no inherent distinction in high-level/low-level classes, unless you attribute such levels via your packaging. A common way of packaging is:

  • com.mycompany.myapp: main class; MyApp (with a main method)
  • com.mycompany.myapp.model: domain model classes; Customer, Order, etc.
  • com.mycompany.myapp.ui: user interface (presentation or view) code
  • com.mycompany.myapp.service: services within your application, i.e. 'business logic'
  • com.mycompany.myapp.util: helper classes used in several places

this suggests a standalone Java app, it might be different if it is a webapp using one of the many frameworks.

These packages correspond to a directory hierarchy in your project. When using Eclipse, the root of such a hierarchy is called a 'source directory'. A project can define multiple source directories, commonly a 'main' and a 'test' source directory.

Example of files in your project:

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

And inside utilities_1_0.jar:

com/acme/foo/BarUtils.class

BarUtils.class this is a compiled java class, so in platform independent bytecode form that can be run on any JVM. Usually jarfiles only contain the compiled classes although you can sometimes download a version of the jar that also contains the source (.java) files. This is useful if you want to be able to read the original source code of a jar file you are using.

In the example above Bar, BarTest and BarUtils are all in the same package com.acme.foo but physically reside in different locations on your harddisk.

Classes that reside directly in a source directory are in the 'default package', it is usually not a good idea to keep classes there because it is not clear to which company and application the class belongs and you can get name conflicts if any jar file you add to your classpath contains a class with the same name in the default package.

Now if you deploy this application, it would normally be compiled into .class files and bundled in a .jar (which is basically a fancy name for a .zip file plus some manifest info). Making a .jar is not necessary to run the application, but handy when deploying/distributing your application. Using the manifest info you can make a .jar file 'executable', so that a user can easily run it, see [a].

Usually you will also be using several libraries, i.e. existing .jar files you obtained from the Internet. Very common examples are log4j (a logging framework) or JDBC libraries for accessing a database etc. Also you might have your own sub-modules that are deployed in separate jarfiles (like 'utilities_1_0.jar' above). How things are split over jarfiles is a deployment/distribution matter, they still all share the universal namespace for Java source code. So in effect, you could unzip all the jarfiles and put the contents in one big directory structure if you wanted to (but you generally don't).

When running a Java application which uses/consists of multiple libraries, you run into what is commonly referred to as 'Classpath hell'. One of the biggest drawbacks of Java as we know it. (note: help is supposedly on the way). To run a Java application on the command line (i.e. not from Eclipse) you have to specify every single .jar file location on the classpath. When you are using one of Java's many frameworks (Maven, Spring, OSGi, Gradle) there is usually some form of support to alleviate this pain. If you are building a web application you would generally just have to adhere to its layering/deployment conventions to be able to easily deploy the thing in the web container of your choice (Tomcat, Jetty, Glassfish).

I hope this gives some general insight in how things work in Java!

[a] To make an executable jar of the MyApp application you need a JDK on your path. Then use the following command line in your compile (bin or target) directory:

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

You can then execute it from the command line with:

java -jar myapp.jar

or by double-clicking the jar file. Note you won't see the Java console in that case so this is only useful for applications that have their own GUI (like a Swing app) or that may run in the background (like a socket server).



回答2:

Maven has a well thought out standard directory layout. Even if you are not using it Maven directly, you can think of this as a defacto standard. Maven "multi module" projects are a fair analogy to the .net multiple assembly layout that you described.



回答3:

There are two things you need to clarify before this question can be answered:

  1. Which source code repository will you use?
  2. Which build system will you use to automatically build artifacts outside of Eclipse?

The answers will strongly influence your options.

We have opted for "one Eclipse project pr component" which may be either a library or a finished runnable/executable jar. This has made it easy to automate with Hudson. Our usage of CVS is also easier, since single projects do not have multiple responsibilities.

Note, each project may contain several source folders separating e.g. test code from configuration from Java source. That is not as important as simplifying your structure.



回答4:

Typically you would create related/sub projects as different Projects in Eclipse.