Multimodul Maven-applikasjon med Java-moduler

1. Oversikt

Java Platform Module System (JPMS) gir mer pålitelighet, bedre separasjon av bekymringer og sterkere innkapsling til Java-applikasjoner. Det er imidlertid ikke et byggeverktøy det mangler muligheten for automatisk administrering av prosjektavhengigheter.

Selvfølgelig kan vi lure på om vi kan bruk veletablerte byggeverktøy, som Maven eller Gradle, i modulariserte applikasjoner.

Egentlig kan vi! I denne veiledningen, vi lærer hvordan du lager en multimodul Maven-applikasjon ved hjelp av Java-moduler.

2. Innkapsling av Maven-moduler i Java-moduler

Siden modularitet og avhengighetsadministrasjon er ikke gjensidig utelukkende begreper i Java, vi kan sømløst integrere JPMS, for eksempel med Maven, og dermed utnytte det beste fra begge verdener.

I et standard multimodul-Maven-prosjekt legger vi til en eller flere Maven-moduler ved å plassere dem under prosjektets rotmappe og erklære dem i den overordnede POM, innenfor seksjon.

I sin tur redigerer vi POM for hver barnemodul og spesifiserer avhengighet via standarden <groupId>, <artifactId> og <versjon> koordinater.

De reaktor mekanisme i Maven - ansvarlig for håndtering av multimodulprosjekter - tar seg av å bygge hele prosjektet i riktig rekkefølge.

I dette tilfellet bruker vi i utgangspunktet den samme designmetoden, men med en subtil, men grunnleggende variant: Vi pakker hver Maven-modul inn i en Java-modul ved å legge til modulbeskrivelsesfilen, module-info.java.

3. Parent Maven-modulen

For å demonstrere hvordan modularitet og avhengighetsadministrasjon fungerer bra sammen, bygger vi et grunnleggende demo-multimodul Maven-prosjekt, hvis funksjonalitet vil bli innsnevret til å bare hente noen domeneobjekter fra et persistenslag.

For å holde koden enkel, bruker vi en vanlig Kart som den underliggende datastrukturen for lagring av domeneobjektene. Selvfølgelig kan vi enkelt bytte lenger ned i veien til en fullverdig relasjonsdatabase.

La oss starte med å definere den overordnede Maven-modulen. For å oppnå dette, la oss lage en rotprosjektkatalog kalt for eksempel multimodulemavenproject (men det kan være noe annet), og legg til foreldrene pom.xml fil:

com.baeldung.multimodulemavenproject multimodulemavenproject 1.0 pom multimodulemavenproject org.apache.maven.plugins maven-compiler-plugin 3.8.0 11 11 UTF-8 

Det er noen detaljer som er verdt å merke seg i definisjonen av foreldrenes POM.

Først og fremst, siden vi bruker Java 11, vi trenger minst Maven 3.5.0 på systemet vårt, da Maven støtter Java 9 og nyere fra den versjonen og utover.

Og vi trenger også minst versjon 3.8.0 av Maven compiler plugin. La oss derfor sørge for å sjekke den nyeste versjonen av programtillegget på Maven Central.

4. Child Maven-modulene

Legg merke til at frem til dette punktet, foreldrenes POM erklærer ikke noen underordnede moduler.

Siden demoprosjektet vårt vil hente noen domeneobjekter fra utholdenhetslaget, lager vi fire Maven-moduler:

  1. enhetsmodul: inneholder en enkel domene klasse
  2. daomodule: holder grensesnittet som kreves for å få tilgang til utholdenhetslaget (en grunnleggende DAO-kontrakt)
  3. userdaomodule: vil inkludere en implementering av daomoduleGrensesnitt
  4. mainappmodule: prosjektets inngangspunkt

4.1. De enhetsmodul Maven-modul

La oss nå legge til den første underordnede Maven-modulen, som bare inneholder en grunnleggende domeneklasse.

Under prosjektets rotkatalog, la oss lage entitymodule / src / main / java / com / baeldung / entity katalogstruktur og legg til en Bruker klasse:

public class User {private final Strengnavn; // standard konstruktør / getter / toString}

La oss deretter inkludere modulens pom.xml fil:

 com.baeldung.multimodulemavenproject multimodulemavenproject 1.0 com.baeldung.entitymodule entitymodule 1.0 jar entitymodule

Som vi kan se, er Enhet modulen har ingen avhengigheter av andre moduler, og krever heller ikke flere Maven-gjenstander, da den bare inkluderer Bruker klasse.

Nå må vi kapsle inn Maven-modulen i en Java-modul. For å oppnå dette, la oss bare plassere følgende modulbeskrivelsesfil (module-info.java) under entitymodule / src / main / java katalog:

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

Til slutt, la oss legge til den underordnede Maven-modulen i den overordnede POM:

 enhetsmodul 

4.2. De daomodule Maven-modul

La oss lage en ny Maven-modul som inneholder et enkelt grensesnitt. Dette er praktisk for å definere en abstrakt kontrakt for å hente generiske typer fra utholdenhetslaget.

Faktisk er det en veldig overbevisende grunn til å plassere dette grensesnittet i en egen Java-modul. Ved å gjøre dette har vi en abstrakt, sterkt frakoblet kontrakt, som er lett å gjenbruke i forskjellige sammenhenger. I kjernen er dette en alternativ implementering av Dependency Inversion Principle, som gir en mer fleksibel design.

La oss derfor lage daomodule / src / main / java / com / baeldung / dao katalogstruktur under prosjektets rotkatalog, og legg til den Dao grensesnitt:

offentlig grensesnitt Dao {Valgfritt findById (int id); Liste findAll (); }

La oss nå definere modulens pom.xml fil:

 // foreldrekoordinater com.baeldung.daomodule daomodule 1.0 jar daomodule

Den nye modulen krever heller ikke andre moduler eller gjenstander, så vi pakker den bare inn i en Java-modul. La oss lage modulbeskrivelsen under daomodule / src / main / java katalog:

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

Til slutt, la oss legge til modulen i den overordnede POM:

 entitymodule daomodule 

4.3. De userdaomodule Maven-modul

Deretter la oss definere Maven-modulen som inneholder en implementering av Dao grensesnitt.

Under prosjektets rotkatalog, la oss lage userdaomodule / src / main / java / com / baeldung / userdao katalogstruktur, og legg til det følgende UserDao klasse:

offentlig klasse UserDao implementerer Dao {private final Map brukere; // standardkonstruktør @ Override public Valgfri findById (int id) {return Optional.ofNullable (users.get (id)); } @Override public List findAll () {return new ArrayList (users.values ​​()); }}

Enkelt sagt, den UserDao klasse gir et grunnleggende API som lar oss hente Bruker gjenstander fra utholdenhetslaget.

For å holde ting enkelt, brukte vi a Kart som støttedatastruktur for å vedvare domeneobjektene. Selvfølgelig er det mulig å gi en grundigere implementering som bruker for eksempel Hibernates enhetsleder.

La oss definere Maven-modulens POM:

 // foreldrekoordinater com.baeldung.userdaomodule userdaomodule 1.0 jar userdaomodule com.baeldung.entitymodule entitymodule 1.0 com.baeldung.daomodule daomodule 1.0 

I dette tilfellet er ting litt annerledes, som userdaomodule modulen krever entitymodule og daomodule moduler. Derfor la vi dem til som avhengigheter i pom.xml fil.

Vi trenger fortsatt å kapsle denne Maven-modulen i en Java-modul. Så la oss legge til følgende modulbeskrivelse under userdaomodule / src / main / java katalog:

modul com.baeldung.userdaomodule {krever com.baeldung.entitymodule; krever com.baeldung.daomodule; gir com.baeldung.daomodule.Dao med com.baeldung.userdaomodule.UserDao; eksport com.baeldung.userdaomodule; } 

Til slutt må vi legge til denne nye modulen i den overordnede POM:

 entitymodule daomodule userdaomodule 

Fra et høyt nivå er det lett å se det de pom.xml filen og modulbeskriveren spiller forskjellige roller. Allikevel kompletterer de hverandre pent.

La oss si at vi trenger å oppdatere versjonene av entitymodule og daomodule Maven gjenstander. Vi kan enkelt gjøre dette uten å måtte endre avhengighetene i modulbeskrivelsen. Maven vil ta seg av å inkludere de rette gjenstandene for oss.

På samme måte kan vi endre tjenesteimplementeringen som modulen gir ved å endre “Gir..med” direktivet i modulbeskrivelsen.

Vi får mye når vi bruker Maven- og Java-moduler sammen. Førstnevnte gir funksjonaliteten til automatisk, sentralisert avhengighetsstyring, mens sistnevnte gir de iboende fordelene med modularitet.

4.4. De mainappmodule Maven-modul

I tillegg må vi definere Maven-modulen som inneholder prosjektets hovedklasse.

Som vi gjorde før, la oss lage mainappmodule / src / main / java / mainapp katalogstruktur under rotkatalogen, og legg til følgende: applikasjon klasse:

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

De applikasjon klasse hoved() metoden er ganske enkel. For det første fyller den en HashMap med et par Bruker gjenstander. Deretter bruker den en UserDao eksempel for å hente dem fra Kart, og deretter viser den dem til konsollen.

I tillegg må vi også definere modulens pom.xml fil:

 // foreldrekoordinater com.baeldung.mainappmodule mainappmodule 1.0 jar mainappmodule com.baeldung.entitymodule entitymodule 1.0 com.baeldung.daomodule daomodule 1.0 com.baeldung.userdaomodule userdaomodule 1.0 

Modulens avhengighet er ganske selvforklarende. Så vi trenger bare å plassere modulen i en Java-modul. Derfor, under mainappmodule / src / main / java katalogstruktur, la oss ta med modulbeskrivelsen:

module com.baeldung.mainappmodule {krever com.baeldung.entitypmodule; krever com.baeldung.userdaopmodule; krever com.baeldung.daopmodule; bruker com.baeldung.daopmodule.Dao; } 

Til slutt, la oss legge til denne modulen i den overordnede POM:

 entitymodule daomodule userdaomodule mainappmodule 

Med alle Maven-moduler som allerede er på plass, og pent innkapslet i Java-moduler, ser du hvordan prosjektets struktur ser ut:

multimodulemavenproject (rotkatalogen) 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. Kjøre applikasjonen

Til slutt, la oss kjøre applikasjonen, enten fra IDE eller fra en konsoll.

Som vi kanskje forventer, bør vi se et par Bruker gjenstander som er skrevet ut til konsollen når applikasjonen starter:

Bruker {name = Julie} Bruker {name = David} 

6. Konklusjon

I denne opplæringen lærte vi på en pragmatisk måte hvordan få Maven og JPMS til å fungere side om side, i utviklingen av et grunnleggende multimodul Maven-prosjekt som bruker Java-moduler.

Som vanlig er alle kodeeksemplene som vises i denne opplæringen tilgjengelig på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found