如何管理 Java 项目结构

JavaJavaBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

有效的项目结构对于 Java 开发的成功至关重要。本综合指南探讨了组织 Java 项目的基本原则,为开发者提供了创建可扩展、可维护且结构良好的软件解决方案的实用见解。

创建基本的 Java 项目结构

Java 项目遵循特定的组织规范,这些规范有助于开发者有效地管理代码。在这一步中,你将手动创建一个简单的 Java 项目结构,以了解其基本组件。

理解 Java 项目组件

一个 Java 项目通常包含:

  • 源代码文件(.java
  • 编译后的字节码文件(.class
  • 资源文件(配置文件、图像等)
  • 文档

创建简单的项目结构

让我们从在你的工作空间中创建一个基本的项目结构开始。我们将构建一个简单的“HelloWorld”应用程序来演示这些概念。

  1. 首先,在你的 LabEx 环境中打开一个终端。你的终端应该已经位于 /home/labex/project 目录下。

  2. 为我们的 Java 应用程序创建一个项目目录:

mkdir -p hello-java-app/src
cd hello-java-app
  1. src 目录内,创建一个简单的 Java 类文件:
mkdir -p src/com/example/app
  1. 现在,让我们创建第一个 Java 类。打开代码编辑器,在路径 hello-java-app/src/com/example/app/ 下创建一个名为 HelloWorld.java 的新文件:
package com.example.app;

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, Java Project World!");
    }
}
  1. 让我们编译这个 Java 代码。在终端中,回到项目根目录并运行:
cd /home/labex/project/hello-java-app
mkdir -p bin
javac -d bin src/com/example/app/HelloWorld.java

如果编译成功,输出应该显示没有错误。

  1. 现在,运行编译后的 Java 应用程序:
java -cp bin com.example.app.HelloWorld

你应该会看到如下输出:

Hello, Java Project World!

理解项目结构

让我们回顾一下我们所创建的内容:

hello-java-app/
├── bin/              ## 编译后的字节码(.class 文件)
│   └── com/
│       └── example/
│           └── app/
│               └── HelloWorld.class
└── src/              ## 源代码(.java 文件)
    └── com/
        └── example/
            └── app/
                └── HelloWorld.java

这个结构遵循以下原则:

  • 源代码分离:所有 Java 源文件都位于 src 目录中
  • 包结构com.example.app 包对应于目录 com/example/app/
  • 编译代码分离:字节码文件位于单独的 bin 目录中

关键概念

  • :Java 使用包来组织类并避免命名冲突
  • 目录结构:包名直接映射到目录结构
  • 类路径-cp 标志告诉 Java 在哪里可以找到编译后的类

你现在已经手动创建了一个基本的 Java 项目结构。这个基础将帮助你理解实际应用中使用的更复杂的项目结构。

使用包组织 Java 代码

在这一步中,你将学习如何使用包来组织 Java 代码,并创建一个包含多个类的更具结构化的应用程序。合理的包组织对于可维护的 Java 项目至关重要。

理解包的命名规范

Java 包遵循分层命名规范:

  • 以反转的域名开头(例如,com.example
  • 添加项目或组织名称(例如,com.example.project
  • 添加功能区域(例如,com.example.project.model

让我们在项目中实现这种结构。

创建多包项目

我们将构建一个简单的图书馆管理系统,为不同的功能模块使用不同的包:

  1. 导航到你的项目目录:
cd /home/labex/project
mkdir -p library-app/src
cd library-app
  1. 创建结构化的包布局:
mkdir -p src/com/example/library/model
mkdir -p src/com/example/library/service
mkdir -p src/com/example/library/util
  1. 首先,创建一个模型类。打开代码编辑器,在路径 library-app/src/com/example/library/model/ 下创建一个名为 Book.java 的新文件:
package com.example.library.model;

public class Book {
    private String title;
    private String author;
    private int year;

    public Book(String title, String author, int year) {
        this.title = title;
        this.author = author;
        this.year = year;
    }

    // Getters
    public String getTitle() {
        return title;
    }

    public String getAuthor() {
        return author;
    }

    public int getYear() {
        return year;
    }

    @Override
    public String toString() {
        return "Book{title='" + title + "', author='" + author + "', year=" + year + "}";
    }
}
  1. 接下来,在 library-app/src/com/example/library/service/BookService.java 中创建一个服务类:
package com.example.library.service;

import com.example.library.model.Book;
import java.util.ArrayList;
import java.util.List;

public class BookService {
    private List<Book> books = new ArrayList<>();

    public void addBook(Book book) {
        books.add(book);
    }

    public List<Book> getAllBooks() {
        return new ArrayList<>(books);
    }

    public Book findBookByTitle(String title) {
        for (Book book : books) {
            if (book.getTitle().equalsIgnoreCase(title)) {
                return book;
            }
        }
        return null;
    }
}
  1. library-app/src/com/example/library/util/BookFormatter.java 中创建一个工具类:
package com.example.library.util;

import com.example.library.model.Book;

public class BookFormatter {
    public static String formatBookInfo(Book book) {
        return String.format("'%s' by %s (%d)",
            book.getTitle(), book.getAuthor(), book.getYear());
    }
}
  1. 最后,在 library-app/src/com/example/library/LibraryApp.java 中创建主应用程序类:
package com.example.library;

import com.example.library.model.Book;
import com.example.library.service.BookService;
import com.example.library.util.BookFormatter;

public class LibraryApp {
    public static void main(String[] args) {
        // Create service
        BookService bookService = new BookService();

        // Add some books
        bookService.addBook(new Book("The Great Gatsby", "F. Scott Fitzgerald", 1925));
        bookService.addBook(new Book("To Kill a Mockingbird", "Harper Lee", 1960));
        bookService.addBook(new Book("1984", "George Orwell", 1949));

        // Display all books
        System.out.println("Library Catalog:");
        for (Book book : bookService.getAllBooks()) {
            System.out.println(BookFormatter.formatBookInfo(book));
        }

        // Find a specific book
        Book foundBook = bookService.findBookByTitle("1984");
        if (foundBook != null) {
            System.out.println("\nFound book: " + foundBook);
        }
    }
}
  1. 编译所有 Java 文件:
mkdir -p bin
javac -d bin src/com/example/library/model/Book.java src/com/example/library/service/BookService.java src/com/example/library/util/BookFormatter.java src/com/example/library/LibraryApp.java
  1. 运行应用程序:
java -cp bin com.example.library.LibraryApp

你应该会看到如下输出:

Library Catalog:
'The Great Gatsby' by F. Scott Fitzgerald (1925)
'To Kill a Mockingbird' by Harper Lee (1960)
'1984' by George Orwell (1949)

Found book: Book{title='1984', author='George Orwell', year=1949}

理解包结构

让我们来查看一下我们创建的结构:

library-app/
├── bin/                              ## 编译后的字节码
└── src/                              ## 源代码
    └── com/
        └── example/
            └── library/
                ├── model/            ## 数据结构
                │   └── Book.java
                ├── service/          ## 业务逻辑
                │   └── BookService.java
                ├── util/             ## 工具函数
                │   └── BookFormatter.java
                └── LibraryApp.java   ## 主应用程序

包组织原则

这种结构遵循了重要的设计原则:

  1. 关注点分离

    • model 包:包含数据结构
    • service 包:包含业务逻辑
    • util 包:包含工具函数
  2. 逻辑分组:相关的类被分组在同一个包中

  3. 直观导航:包结构使你能够轻松定位特定的功能

  4. 导入管理:类通过导入相互引用,使依赖关系清晰明了

通过以这种方式组织代码,你可以创建更易于维护、可扩展的应用程序,这些应用程序更易于理解和扩展。

使用 Maven 进行项目管理

在这一步中,你将学习如何使用 Apache Maven 来管理你的 Java 项目。Maven 是一个强大的构建自动化和依赖管理工具,它简化了项目的设置和维护。

理解 Maven

Maven 提供以下功能:

  • 标准的项目结构
  • 依赖管理
  • 构建自动化
  • 项目信息管理
  • 跨项目的一致构建流程

设置 Maven 项目

让我们使用 Maven 创建一个新项目:

  1. 首先,检查 Maven 是否已安装:
mvn --version

你应该会看到类似如下的输出:

Apache Maven 3.6.3
Maven home: /usr/share/maven
Java version: 11.0.18, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "5.15.0-1036-azure", arch: "amd64", family: "unix"
  1. 导航到你的项目目录:
cd /home/labex/project
  1. 使用原型(项目模板)创建一个新的 Maven 项目:
mvn archetype:generate \
  -DgroupId=com.example.calculator \
  -DartifactId=simple-calculator \
  -DarchetypeArtifactId=maven-archetype-quickstart \
  -DarchetypeVersion=1.4 \
  -DinteractiveMode=false

此命令将创建一个具有标准目录结构的新项目。

  1. 查看项目结构:
cd simple-calculator
ls -la

你应该会看到类似如下的输出:

total 24
drwxr-xr-x 4 labex labex 4096 ... .
drwxr-xr-x 6 labex labex 4096 ... ..
-rw-r--r-- 1 labex labex  174 ... .gitignore
-rw-r--r-- 1 labex labex  720 ... pom.xml
drwxr-xr-x 4 labex labex 4096 ... src

这里的关键文件是 pom.xml(项目对象模型),它定义了项目配置。

  1. 查看 Maven 标准目录布局:
find src -type d

你应该会看到:

src
src/main
src/main/java
src/main/java/com
src/main/java/com/example
src/main/java/com/example/calculator
src/test
src/test/java
src/test/java/com
src/test/java/com/example
src/test/java/com/example/calculator

这就是 Maven 标准目录布局:

  • src/main/java:源代码
  • src/main/resources:资源文件
  • src/test/java:测试代码
  • src/test/resources:测试资源
  1. 让我们看看生成的 App.java 文件:
cat src/main/java/com/example/calculator/App.java

你应该会看到一个简单的“Hello World”类:

package com.example.calculator;

/**
 * Hello world!
 *
 */
public class App
{
    public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
    }
}

增强 Maven 项目

让我们通过添加更多类来增强我们的计算器项目:

  1. src/main/java/com/example/calculator/ 中创建一个名为 Calculator.java 的新文件:
package com.example.calculator;

public class Calculator {

    public int add(int a, int b) {
        return a + b;
    }

    public int subtract(int a, int b) {
        return a - b;
    }

    public int multiply(int a, int b) {
        return a * b;
    }

    public double divide(int a, int b) {
        if (b == 0) {
            throw new ArithmeticException("Cannot divide by zero");
        }
        return (double) a / b;
    }
}
  1. 现在,修改现有的 App.java 文件以使用我们的 Calculator 类:
package com.example.calculator;

/**
 * Simple Calculator Application
 */
public class App
{
    public static void main( String[] args )
    {
        Calculator calculator = new Calculator();

        // Perform some calculations
        System.out.println("Addition: 5 + 3 = " + calculator.add(5, 3));
        System.out.println("Subtraction: 10 - 4 = " + calculator.subtract(10, 4));
        System.out.println("Multiplication: 6 * 7 = " + calculator.multiply(6, 7));
        System.out.println("Division: 20 / 4 = " + calculator.divide(20, 4));

        System.out.println("Calculator application completed successfully!");
    }
}
  1. 使用 Maven 构建项目:
mvn compile

你应该会看到以如下内容结尾的输出:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
  1. 将应用程序打包成 JAR 文件:
mvn package

此命令会编译你的代码、运行测试并打包应用程序。

  1. 运行打包后的应用程序:
java -cp target/simple-calculator-1.0-SNAPSHOT.jar com.example.calculator.App

你应该会看到如下输出:

Addition: 5 + 3 = 8
Subtraction: 10 - 4 = 6
Multiplication: 6 * 7 = 42
Division: 20 / 4 = 5.0
Calculator application completed successfully!

理解 Maven POM 文件

项目对象模型(POM)文件包含项目配置。在编辑器中打开 pom.xml 文件并查看其结构:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example.calculator</groupId>
  <artifactId>simple-calculator</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>simple-calculator</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <!-- Build configuration... -->
</project>

POM 文件中的关键元素:

  • groupId:组织或项目标识符
  • artifactId:项目名称
  • version:项目版本
  • dependencies:项目使用的外部库
  • build:项目构建配置

Maven 关键命令

以下是一些重要的 Maven 命令:

  • mvn compile:编译源代码
  • mvn test:运行测试
  • mvn package:创建可分发的包(JAR、WAR)
  • mvn install:将包安装到本地仓库
  • mvn clean:移除构建产物(target 目录)
  • mvn clean install:清理和安装的组合

Maven 通过提供规范、依赖管理和构建自动化,极大地简化了 Java 项目管理。这种标准化的方法有助于开发者专注于编写代码,而不是管理项目结构。

总结

在本次实验中,你通过实践学习了管理 Java 项目结构的重要策略:

  1. 你首先手动创建了一个基本的 Java 项目结构,了解了源目录、包和编译代码组织的基本组成部分。

  2. 接着,你进一步创建了一个具有合理包组织的更复杂项目,通过将功能划分为模型、服务和工具包来实现关注点分离。

  3. 最后,你学习了如何使用强大的构建自动化工具 Maven 来创建和管理具有依赖管理和自动化构建流程的标准化 Java 项目。

这些基础技能将为你未来的 Java 开发工作奠定坚实的基础,使你能够创建组织良好、可维护且可扩展的应用程序。通过遵循既定的项目结构规范和最佳实践,你将能够更有效地与其他开发者协作,并产出更高质量的代码。