简介
有效的项目结构对于 Java 开发的成功至关重要。本综合指南探讨了组织 Java 项目的基本原则,为开发者提供了创建可扩展、可维护且结构良好的软件解决方案的实用见解。
有效的项目结构对于 Java 开发的成功至关重要。本综合指南探讨了组织 Java 项目的基本原则,为开发者提供了创建可扩展、可维护且结构良好的软件解决方案的实用见解。
Java 项目遵循特定的组织规范,这些规范有助于开发者有效地管理代码。在这一步中,你将手动创建一个简单的 Java 项目结构,以了解其基本组件。
一个 Java 项目通常包含:
.java
).class
)让我们从在你的工作空间中创建一个基本的项目结构开始。我们将构建一个简单的“HelloWorld”应用程序来演示这些概念。
首先,在你的 LabEx 环境中打开一个终端。你的终端应该已经位于 /home/labex/project
目录下。
为我们的 Java 应用程序创建一个项目目录:
mkdir -p hello-java-app/src
cd hello-java-app
src
目录内,创建一个简单的 Java 类文件:mkdir -p src/com/example/app
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!");
}
}
cd /home/labex/project/hello-java-app
mkdir -p bin
javac -d bin src/com/example/app/HelloWorld.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
这个结构遵循以下原则:
src
目录中com.example.app
包对应于目录 com/example/app/
bin
目录中-cp
标志告诉 Java 在哪里可以找到编译后的类你现在已经手动创建了一个基本的 Java 项目结构。这个基础将帮助你理解实际应用中使用的更复杂的项目结构。
在这一步中,你将学习如何使用包来组织 Java 代码,并创建一个包含多个类的更具结构化的应用程序。合理的包组织对于可维护的 Java 项目至关重要。
Java 包遵循分层命名规范:
com.example
)com.example.project
)com.example.project.model
)让我们在项目中实现这种结构。
我们将构建一个简单的图书馆管理系统,为不同的功能模块使用不同的包:
cd /home/labex/project
mkdir -p library-app/src
cd library-app
mkdir -p src/com/example/library/model
mkdir -p src/com/example/library/service
mkdir -p src/com/example/library/util
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 + "}";
}
}
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;
}
}
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());
}
}
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);
}
}
}
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
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 ## 主应用程序
这种结构遵循了重要的设计原则:
关注点分离:
model
包:包含数据结构service
包:包含业务逻辑util
包:包含工具函数逻辑分组:相关的类被分组在同一个包中
直观导航:包结构使你能够轻松定位特定的功能
导入管理:类通过导入相互引用,使依赖关系清晰明了
通过以这种方式组织代码,你可以创建更易于维护、可扩展的应用程序,这些应用程序更易于理解和扩展。
在这一步中,你将学习如何使用 Apache Maven 来管理你的 Java 项目。Maven 是一个强大的构建自动化和依赖管理工具,它简化了项目的设置和维护。
Maven 提供以下功能:
让我们使用 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"
cd /home/labex/project
mvn archetype:generate \
-DgroupId=com.example.calculator \
-DartifactId=simple-calculator \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.4 \
-DinteractiveMode=false
此命令将创建一个具有标准目录结构的新项目。
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
(项目对象模型),它定义了项目配置。
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
:测试资源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!" );
}
}
让我们通过添加更多类来增强我们的计算器项目:
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;
}
}
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!");
}
}
mvn compile
你应该会看到以如下内容结尾的输出:
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
mvn package
此命令会编译你的代码、运行测试并打包应用程序。
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!
项目对象模型(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 命令:
mvn compile
:编译源代码mvn test
:运行测试mvn package
:创建可分发的包(JAR、WAR)mvn install
:将包安装到本地仓库mvn clean
:移除构建产物(target 目录)mvn clean install
:清理和安装的组合Maven 通过提供规范、依赖管理和构建自动化,极大地简化了 Java 项目管理。这种标准化的方法有助于开发者专注于编写代码,而不是管理项目结构。
在本次实验中,你通过实践学习了管理 Java 项目结构的重要策略:
你首先手动创建了一个基本的 Java 项目结构,了解了源目录、包和编译代码组织的基本组成部分。
接着,你进一步创建了一个具有合理包组织的更复杂项目,通过将功能划分为模型、服务和工具包来实现关注点分离。
最后,你学习了如何使用强大的构建自动化工具 Maven 来创建和管理具有依赖管理和自动化构建流程的标准化 Java 项目。
这些基础技能将为你未来的 Java 开发工作奠定坚实的基础,使你能够创建组织良好、可维护且可扩展的应用程序。通过遵循既定的项目结构规范和最佳实践,你将能够更有效地与其他开发者协作,并产出更高质量的代码。