CodeGym /Các khóa học /JAVA 25 SELF /Xây dựng các dự án đa mô-đun: Maven, Gradle, IDEA

Xây dựng các dự án đa mô-đun: Maven, Gradle, IDEA

JAVA 25 SELF
Mức độ , Bài học
Có sẵn

1. Xây dựng dự án mô-đun: nguyên tắc cơ bản

Trình biên dịch và đường dẫn mô-đun (module-path)

Trước khi có mô-đun, toàn bộ ứng dụng được biên dịch và chạy bằng cái gọi là classpath — chỉ là danh sách thư mục và tệp JAR nơi Java tìm các lớp. Trong hệ thống mô-đun xuất hiện một thành phần mới — module-path. Giờ đây, trình biên dịch và JVM cần biết không chỉ vị trí các lớp, mà còn chúng thuộc mô-đun nào, có những phụ thuộc gì và những package nào được export.

Điểm then chốt:

  • Với các dự án mô-đun, hãy dùng --module-path thay vì -classpath.
  • Trình biên dịch và JVM phải nhìn thấy tất cả mô-đun mà ứng dụng của bạn cần (và các phụ thuộc của chúng).

Ví dụ: biên dịch mô-đun thủ công

Giả sử bạn có hai mô-đun: coreapp, trong đó app phụ thuộc vào core.

Cấu trúc thư mục:

project-root/
  core/
    src/
      main/
        java/
          module-info.java
          com/example/core/...
  app/
    src/
      main/
        java/
          module-info.java
          com/example/app/...

Biên dịch thủ công (minh họa):

# Biên dịch core trước
javac -d out/core core/src/main/java/module-info.java core/src/main/java/com/example/core/*.java

# Sau đó biên dịch app, chỉ định module-path trỏ tới core
javac --module-path out/core -d out/app app/src/main/java/module-info.java app/src/main/java/com/example/app/*.java

Chạy:

java --module-path out/core:out/app -m app/com.example.app.Main

Trong các dự án thực tế, bạn không cần làm việc này thủ công — hãy dùng Maven/Gradle hoặc IDE.

2. Maven: xây dựng các dự án đa mô-đun

Cấu trúc dự án đa mô-đun trong Maven

Maven từ lâu đã hỗ trợ cấu trúc với nhiều mô-đun (submodules). Nay, với hệ thống mô-đun của Java, các “mô-đun” của Maven thường trùng với mô-đun Java, nhưng không phải lúc nào cũng vậy: mô-đun Maven là một tiểu dự án, còn mô-đun Java là thứ được mô tả trong module-info.java. Thông thường một mô-đun Maven = một mô-đun Java.

Cấu trúc điển hình:

myproject/
  pom.xml                # Parent POM
  core/
    pom.xml              # Mô-đun core
    src/main/java/
      module-info.java
      com/example/core/...
  app/
    pom.xml              # Mô-đun app
    src/main/java/
      module-info.java
      com/example/app/...

Ví dụ parent POM (myproject/pom.xml):

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>myproject</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>pom</packaging>
  <modules>
    <module>core</module>
    <module>app</module>
  </modules>
</project>

Ví dụ POM cho mô-đun core (core/pom.xml):

<project>
  <parent>
    <groupId>com.example</groupId>
    <artifactId>myproject</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <artifactId>core</artifactId>
  <dependencies>
    <!-- Ở đây có thể có các phụ thuộc, ví dụ vào các mô-đun khác hoặc thư viện bên thứ ba -->
  </dependencies>
</project>

Ví dụ POM cho mô-đun app (app/pom.xml):

<project>
  <parent>
    <groupId>com.example</groupId>
    <artifactId>myproject</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <artifactId>app</artifactId>
  <dependencies>
    <dependency>
      <groupId>com.example</groupId>
      <artifactId>core</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
  </dependencies>
</project>

Quan trọng:

  • Nếu trong app cần core, trong module-info.java của mô-đun app phải có requires core;
  • Maven sẽ tự xử lý phụ thuộc nếu bạn khai báo đúng <dependency><module>.

Maven xử lý module-info.java như thế nào

  • Maven tự động biên dịch module-info.java cùng với các lớp khác.
  • Nếu bạn có phụ thuộc mô-đun, Maven sẽ thêm chúng vào module-path khi biên dịch và khi chạy.
  • Nếu bạn dùng plugin cũ hoặc Java dưới 9 — hệ thống mô-đun sẽ không hoạt động.

Chạy ứng dụng mô-đun qua Maven

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.10.1</version>
      <configuration>
        <release>21</release> <!-- hoặc phiên bản Java của bạn -->
      </configuration>
    </plugin>
    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>exec-maven-plugin</artifactId>
      <version>3.1.0</version>
      <configuration>
        <mainClass>com.example.app.Main</mainClass>
        <commandlineArgs></commandlineArgs>
      </configuration>
    </plugin>
  </plugins>
</build>
mvn clean install
mvn -pl app exec:java

Lỗi thường gặp khi làm việc với Maven và mô-đun

Lỗi: “module not found”. Chưa chỉ định đúng module-path hoặc chưa khai báo <dependency> cho artifact phụ thuộc.

Trùng tên mô-đun. Trong dự án không được có hai mô-đun cùng tên (ví dụ, hai module core).

Thiếu export/requires. Nếu quên export package (exports) hoặc khai báo phụ thuộc (requires), sẽ có lỗi biên dịch.

Trộn lẫn classpath và module-path. Đừng dùng plugin/cấu hình lỗi thời không hỗ trợ mô-đun: điều này dẫn đến lỗi khó lường.

3. Gradle: xây dựng các dự án đa mô-đun

Cấu trúc dự án dùng Gradle

myproject/
  settings.gradle
  build.gradle
  core/
    build.gradle
    src/main/java/module-info.java
    src/main/java/com/example/core/...
  app/
    build.gradle
    src/main/java/module-info.java
    src/main/java/com/example/app/...

settings.gradle

rootProject.name = 'myproject'
include 'core', 'app'

build.gradle (ở root)

subprojects {
    apply plugin: 'java'

    java {
        toolchain {
            languageVersion = JavaLanguageVersion.of(21) // hoặc phiên bản Java của bạn
        }
    }

    repositories {
        mavenCentral()
    }
}

build.gradle cho core

plugins {
    id 'java'
}

group = 'com.example'
version = '1.0-SNAPSHOT'

build.gradle cho app

plugins {
    id 'java'
    id 'application'
}

group = 'com.example'
version = '1.0-SNAPSHOT'

dependencies {
    implementation project(':core')
}

application {
    mainModule = 'app' // Tên mô-đun Java của bạn
    mainClass = 'com.example.app.Main'
}

Build và chạy

./gradlew build
./gradlew :app:run

Gradle tự xác định module-path nếu phát hiện module-info.java. Nếu có gì đó không chạy — hãy kiểm tra rằng bạn dùng phiên bản Gradle và plugin mới.

4. IntelliJ IDEA: tạo và cấu hình dự án mô-đun

Tạo dự án mô-đun

  • File → New → Project → Java → bật “Create module-info.java”.
  • Với dự án đa mô-đun: File → New → Module — thêm mô-đun mới vào dự án.
  • Nếu dùng Maven/Gradle — chỉ cần import dự án từ pom.xml hoặc build.gradle.

Cấu trúc trong IDEA

  • Trong Project View, mỗi mô-đun hiển thị như một nhánh riêng.
  • Mỗi mô-đun có module-info.java và mã nguồn riêng.
  • IDEA gợi ý mô-đun nào export/require các package nào (exports/requires).
  • Nếu quên export package hoặc khai báo phụ thuộc — IDEA sẽ tô sáng lỗi.

Kiểm tra module-path, chạy lớp main

  • Trong Run/Debug Configurations, chỉ định:
    • Main class (ví dụ, com.example.app.Main)
    • Module (ví dụ, app)
  • IDEA sẽ tự cấu hình module-path.
  • Nếu chạy qua Maven/Gradle — dùng các cấu hình tương ứng (ví dụ, app [run]).

Nhập mô-đun và thư viện bên ngoài

  • Để làm việc với thư viện bên ngoài (ví dụ, requires java.sql; hoặc các JAR bên thứ ba) — hãy thêm phụ thuộc qua Maven/Gradle.
  • Nếu thư viện không phải mô-đun (không có module-info.java), nó sẽ tự động được đưa vào “unnamed module” (điều này bình thường với hầu hết thư viện).

5. Thực hành: tạo một dự án đa mô-đun đơn giản

Bước 1. Tạo cấu trúc dự án

myproject/
  core/
    src/main/java/module-info.java
    src/main/java/com/example/core/HelloService.java
  app/
    src/main/java/module-info.java
    src/main/java/com/example/app/Main.java

HelloService.java (core):

package com.example.core;

public class HelloService {
    public String getHello() {
        return "Xin chào từ mô-đun core!";
    }
}

module-info.java (core):

module core {
    exports com.example.core;
}

Main.java (app):

package com.example.app;

import com.example.core.HelloService;

public class Main {
    public static void main(String[] args) {
        HelloService service = new HelloService();
        System.out.println(service.getHello());
    }
}

module-info.java (app):

module app {
    requires core;
}

Bước 2. Build và chạy bằng Maven

Ở thư mục gốc dự án, tạo parent pom.xml và hai dự án con (core/pom.xml, app/pom.xml) như ở trên. Trong app/pom.xml thêm phụ thuộc tới core.

mvn clean install
mvn -pl app exec:java

Bước 3. Build và chạy bằng Gradle

Tạo settings.gradle, build.gradle ở root, và một tệp cho mỗi mô-đun. Trong app/build.gradle, khai báo phụ thuộc tới coremainClass.

./gradlew build
./gradlew :app:run

Bước 4. Import và chạy trong IntelliJ IDEA

  • Mở thư mục gốc dự án qua File → Open.
  • IDEA nhận diện cấu trúc Maven/Gradle và tạo các mô-đun.
  • Trong mỗi mô-đun có thể mở module-info.java, IDEA sẽ hiển thị quan hệ giữa các mô-đun.
  • Chạy Main.java qua menu ngữ cảnh (“Run Main.main()”) — IDEA sẽ tự thiết lập module-path.

6. Các lỗi thường gặp khi build dự án mô-đun

Lỗi số 1: module-path không đúng. Nếu khi chạy hoặc biên dịch xuất hiện thông báo như “module not found” hoặc “package is not visible”, rất có thể bạn chưa chỉ định đúng module-path hoặc quên thêm phụ thuộc trong pom.xml/build.gradle.

Lỗi số 2: trùng tên mô-đun. Trong dự án không được có hai mô-đun cùng tên (ví dụ, hai module core). Điều này dẫn tới lỗi biên dịch.

Lỗi số 3: package không được export. Nếu lớp nằm trong package không được export qua exports trong module-info.java, nó sẽ không khả dụng với mô-đun khác, kể cả khi là public. Sẽ có lỗi biên dịch khi cố sử dụng lớp như vậy.

Lỗi số 4: thiếu requires. Nếu mô-đun sử dụng lớp từ mô-đun khác nhưng không chỉ định requires trong module-info.java, trình biên dịch sẽ báo lỗi.

Lỗi số 5: không tương thích với thư viện bên ngoài. Việc không khớp giữa mô-đun và các thư viện không có module-info.java (chúng rơi vào “unnamed module”) thường không gây cản trở, nhưng trong một số cấu hình có thể cần thiết lập bổ sung.

Lỗi số 6: chạy sai mô-đun. Trong cấu hình chạy của IDEA hoặc Maven/Gradle chỉ định sai lớp main hoặc mô-đun — ứng dụng sẽ không khởi động. Hãy kiểm tra Main, mainModule/module và profile sử dụng.

1
Nhiệm vụ
JAVA 25 SELF, mức độ, bài học
Đã khóa
Xây dựng pháo đài dự án đa module 🏰
Xây dựng pháo đài dự án đa module 🏰
1
Nhiệm vụ
JAVA 25 SELF, mức độ, bài học
Đã khóa
Khởi động trái tim ứng dụng bằng Maven ✨
Khởi động trái tim ứng dụng bằng Maven ✨
1
Khảo sát/đố vui
, cấp độ , bài học
Không có sẵn
Mô-đun và cấu trúc dự án
Mô-đun và cấu trúc dự án
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION