Java >> Java tutorial >  >> Tag >> maven

Multi-Module Maven-applikation med Java-moduler

1. Oversigt

Java Platform Module System (JPMS) tilføjer mere pålidelighed, bedre adskillelse af bekymringer og stærkere indkapsling til Java-applikationer. Det er dog ikke et byggeværktøj, og derfor mangler det muligheden for automatisk at administrere projektafhængigheder.

Selvfølgelig kan vi spekulere på, om vi kan bruge veletablerede byggeværktøjer som Maven eller Gradle , i modulære applikationer.

Det kan vi faktisk! I denne vejledning lærer vi, hvordan man opretter en Maven-applikation med flere moduler ved hjælp af Java-moduler .

2. Indkapsling af Maven-moduler i Java-moduler

Da modularitet og afhængighedsstyring ikke er gensidigt udelukkende begreber i Java, vi kan problemfrit integrere JPMS, for eksempel med Maven, og dermed udnytte det bedste fra begge verdener.

I et standard Maven-projekt med flere moduler tilføjer vi et eller flere underordnede Maven-moduler ved at placere dem under projektets rodmappe og erklære dem i den overordnede POM inden for afsnit.

Til gengæld redigerer vi hvert underordnede moduls POM og specificerer dets afhængigheder via standarden <groupId> , <artifactId> og <version> koordinater.

reaktoren mekanisme i Maven — ansvarlig for håndtering af multi-modul projekter — sørger for at bygge hele projektet i den rigtige rækkefølge.

I dette tilfælde vil vi grundlæggende bruge den samme designmetode, men med en subtil, men grundlæggende variant:vi pakker hvert Maven-modul ind i et Java-modul ved at tilføje modulbeskrivelsesfilen til det , module-info.java .

3. Forældre Maven-modulet

For at demonstrere, hvordan modularitet og afhængighedsstyring fungerer godt sammen, bygger vi et grundlæggende demo multi-modul Maven-projekt,hvis funktionalitet vil blive indsnævret til blot at hente nogle domæneobjekter fra et persistenslag .

For at holde koden enkel, bruger vi et almindeligt kort som den underliggende datastruktur til lagring af domæneobjekterne. Selvfølgelig kan vi nemt skifte længere hen ad vejen til en fuldt udbygget relationsdatabase.

Lad os starte med at definere det overordnede Maven-modul. For at opnå dette, lad os oprette en rodprojektmappe kaldet for eksempel multimodulemavenproject (men det kan være hvad som helst andet), og tilføj det overordnede pom.xml fil:

<groupId>com.baeldung.multimodulemavenproject</groupId>
<artifactId>multimodulemavenproject</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<name>multimodulemavenproject</name>
 
<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>
 
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

Der er et par detaljer, der er værd at bemærke i definitionen af ​​den overordnede POM.

For det første, da vi bruger Java 11, skal vi mindst bruge Maven 3.5.0 på vores system, da Maven understøtter Java 9 og nyere fra den version og frem .

Og vi har også brug for mindst version 3.8.0 af Maven compiler plugin. Lad os derfor sørge for at tjekke den seneste version af pluginnet på Maven Central.

4. Child Maven-modulerne

Bemærk, at indtil dette tidspunkt erklærer den overordnede POM ikke nogen underordnede moduler .

Da vores demoprojekt vil hente nogle domæneobjekter fra persistenslaget, vil vi oprette fire underordnede Maven-moduler:

  1. entitetsmodul :vil indeholde en simpel domæneklasse
  2. daomodul :vil indeholde den grænseflade, der kræves for at få adgang til persistenslaget (en grundlæggende DAO-kontrakt)
  3. userdaomodule :vil inkludere en implementering af daomodulet 's grænseflade
  4. mainappmodule :projektets indgangspunkt

4.1. entitetsmodulet Maven Modul

Lad os nu tilføje det første underordnede Maven-modul, som blot inkluderer en grundlæggende domæneklasse.

Under projektets rodmappe, lad os oprette entitymodule/src/main/java/com/baeldung/entity mappestruktur og tilføje en Bruger klasse:

public class User {

    private final String name;

    // standard constructor / getter / toString

}

Lad os derefter inkludere modulets pom.xml fil:

<parent>
    <groupId>com.baeldung.multimodulemavenproject</groupId>
    <artifactId>multimodulemavenproject</artifactId>
    <version>1.0</version>
</parent>
 
<groupId>com.baeldung.entitymodule</groupId>
<artifactId>entitymodule</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<name>entitymodule</name>

Som vi kan se, er Entiteten Modulet har ingen afhængigheder til andre moduler, og det kræver heller ikke yderligere Maven-artefakter, da det kun inkluderer Brugeren klasse.

Nu skal vi indkapsle Maven-modulet i et Java-modul . For at opnå dette, lad os blot placere følgende modulbeskrivelsesfil (module-info.java ) under entitymodule/src/main/java mappe:

module com.baeldung.entitymodule {
    exports com.baeldung.entitymodule;
}

Lad os endelig tilføje det underordnede Maven-modul til den overordnede POM:

<modules>
    <module>entitymodule</module>
</modules>

4.2. daomodulet Maven Modul

Lad os skabe et nyt Maven-modul, der vil indeholde en enkel grænseflade. Dette er praktisk til at definere en abstrakt kontrakt til at hente generiske typer fra persistenslaget.

Faktisk er der en meget overbevisende grund til at placere denne grænseflade i et separat Java-modul. Ved at gøre det har vi en abstrakt, stærkt afkoblet kontrakt, som er nem at genbruge i forskellige sammenhænge. Kernen er dette en alternativ implementering af afhængighedsinversionsprincippet, som giver et mere fleksibelt design.

Lad os derfor oprette daomodule/src/main/java/com/baeldung/dao mappestruktur under projektets rodmappe, og tilføj Dao til den grænseflade:

public interface Dao<T> {

    Optional<T> findById(int id);

    List<T> findAll();

}

Lad os nu definere modulets pom.xml fil:

<parent>
    // parent coordinates
</parent>
 
<groupId>com.baeldung.daomodule</groupId>
<artifactId>daomodule</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<name>daomodule</name>

Det nye modul kræver heller ikke andre moduler eller artefakter, så vi pakker det bare ind i et Java-modul. Lad os oprette modulbeskrivelsen under daomodule/src/main/java mappe:

module com.baeldung.daomodule {
    exports com.baeldung.daomodule;
}

Lad os endelig tilføje modulet til den overordnede POM:

<modules>
    <module>entitymodule</module>
    <module>daomodule</module>
</modules>

4.3. userdaomodulet Maven Modul

Lad os derefter definere Maven-modulet, der indeholder en implementering af Dao grænseflade.

Under projektets rodmappe, lad os oprette userdaomodule/src/main/java/com/baeldung/userdao mappestruktur, og føj følgende UserDao til den klasse:

public class UserDao implements Dao<User> {

    private final Map<Integer, User> users;

    // standard constructor

    @Override
    public Optional<User> findById(int id) {
        return Optional.ofNullable(users.get(id));
    }

    @Override
    public List<User> findAll() {
        return new ArrayList<>(users.values());
    }
}

Simpelt sagt, UserDao klasse giver en grundlæggende API, der giver os mulighed for at hente Bruger objekter fra persistenslaget.

For at gøre tingene enkle brugte vi et kort som understøttende datastruktur for at bevare domæneobjekterne. Det er selvfølgelig muligt at levere en mere grundig implementering, der f.eks. bruger Hibernates entity manager.

Lad os nu definere Maven-modulets POM:

<parent>
    // parent coordinates
</parent>
 
<groupId>com.baeldung.userdaomodule</groupId>
<artifactId>userdaomodule</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<name>userdaomodule</name>
 
<dependencies>
    <dependency>
        <groupId>com.baeldung.entitymodule</groupId>
        <artifactId>entitymodule</artifactId>
        <version>1.0</version>
    </dependency>
    <dependency>
        <groupId>com.baeldung.daomodule</groupId>
        <artifactId>daomodule</artifactId>
        <version>1.0</version>
    </dependency>
</dependencies>

I dette tilfælde er tingene lidt anderledes, da userdaomodulet modulet kræver entitymodulet og daomodule moduler. Det er derfor, vi tilføjede dem som afhængigheder i pom.xml fil.

Vi mangler stadig at indkapsle dette Maven-modul i et Java-modul. Så lad os tilføje følgende modulbeskrivelse under userdaomodule/src/main/java mappe:

module com.baeldung.userdaomodule {
    requires com.baeldung.entitymodule;
    requires com.baeldung.daomodule;
    provides com.baeldung.daomodule.Dao with com.baeldung.userdaomodule.UserDao;
    exports com.baeldung.userdaomodule;
}

Til sidst skal vi tilføje dette nye modul til den overordnede POM:

<modules>
    <module>entitymodule</module>
    <module>daomodule</module>
    <module>userdaomodule</module>
</modules>

Fra en visning på højt niveau er det nemt at se, at den pom.xml fil og modulbeskrivelsen spiller forskellige roller . Alligevel supplerer de hinanden fint.

Lad os sige, at vi skal opdatere versionerne af entitymodulet og daomodule Maven artefakter. Vi kan nemt gøre dette uden at skulle ændre afhængighederne i modulbeskrivelsen. Maven vil sørge for at inkludere de rigtige artefakter til os.

På samme måde kan vi ændre den serviceimplementering, som modulet leverer, ved at ændre "leverer..med" direktiv i modulbeskrivelsen.

Vi vinder meget, når vi bruger Maven og Java moduler sammen. Det førstnævnte giver funktionaliteten af ​​automatisk, centraliseret afhængighedsstyring, mens sidstnævnte giver de iboende fordele ved modularitet .

4.4. hovedappmodulet Maven Modul

Derudover skal vi definere Maven-modulet, der indeholder projektets hovedklasse.

Som vi gjorde før, lad os oprette mainappmodule/src/main/java/mainapp mappestruktur under rodmappen, og tilføj følgende applikation til den klasse:

public class Application {
    
    public static void main(String[] args) {
        Map<Integer, User> users = new HashMap<>();
        users.put(1, new User("Julie"));
        users.put(2, new User("David"));
        Dao userDao = new UserDao(users);
        userDao.findAll().forEach(System.out::println);
    }   
}

Applikationen klasses main() metoden er ret enkel. Først udfylder den et HashMap med et par Bruger genstande. Dernæst bruger den en UserDao forekomst for at hente dem fra kortet, og så viser den dem til konsollen.

Derudover skal vi også definere modulets pom.xml fil:

<parent>
    // parent coordinates
</parent>
 
<groupId>com.baeldung.mainappmodule</groupId>
<artifactId>mainappmodule</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<name>mainappmodule</name>
 
<dependencies>
    <dependency>
        <groupId>com.baeldung.entitymodule</groupId>
         <artifactId>entitymodule</artifactId>
         <version>1.0</version>
    </dependency>
    <dependency>
        <groupId>com.baeldung.daomodule</groupId>
        <artifactId>daomodule</artifactId>
        <version>1.0</version>
    </dependency>
    <dependency>
        <groupId>com.baeldung.userdaomodule</groupId>
        <artifactId>userdaomodule</artifactId>
        <version>1.0</version>
    </dependency>
</dependencies>

Modulets afhængigheder er ret selvforklarende. Så vi skal bare placere modulet inde i et Java-modul. Derfor under mainappmodule/src/main/java mappestruktur, lad os inkludere modulbeskrivelsen:

module com.baeldung.mainappmodule {
    requires com.baeldung.entitypmodule;
    requires com.baeldung.userdaopmodule;
    requires com.baeldung.daopmodule;
    uses com.baeldung.daopmodule.Dao;
}

Lad os endelig tilføje dette modul til den overordnede POM:

<modules>
    <module>entitymodule</module>
    <module>daomodule</module>
    <module>userdaomodule</module>
    <module>mainappmodule</module>
</modules>

Med alle de underordnede Maven-moduler allerede på plads og pænt indkapslet i Java-moduler, ser projektets struktur sådan her ud:

multimodulemavenproject (the root directory)
pom.xml
|-- entitymodule
    |-- src
        |-- main
            | -- java
            module-info.java
            |-- com
                |-- baeldung
                    |-- entity
                    User.class
    pom.xml
|-- daomodule
    |-- src
        |-- main
            | -- java
            module-info.java
            |-- com
                |-- baeldung
                    |-- dao
                    Dao.class
    pom.xml
|-- userdaomodule
    |-- src
        |-- main
            | -- java
            module-info.java
            |-- com
                |-- baeldung
                    |-- userdao
                    UserDao.class
    pom.xml
|-- mainappmodule
    |-- src
        |-- main
            | -- java
            module-info.java
            |-- com
                |-- baeldung
                    |-- mainapp
                    Application.class
    pom.xml

5. Kørsel af applikationen

Lad os endelig køre programmet, enten fra vores IDE eller fra en konsol.

Som vi kunne forvente, skulle vi se et par Bruger objekter, der udskrives til konsollen, når applikationen starter:

User{name=Julie}
User{name=David}

6. Konklusion

I denne tutorial lærte vi på en pragmatisk måde hvordan man sætter Maven og JPMS til at arbejde side om side, i udviklingen af ​​et grundlæggende multi-modul Maven-projekt, der bruger Java-moduler .

Som sædvanlig er alle kodeeksemplerne vist i denne tutorial tilgængelige på GitHub.


Java tag