Benutzerdefinierter Mapper mit MapStruct

1. Übersicht

In diesem Artikel erfahren Sie, wie Sie benutzerdefinierte Mapper mit der MapStruct-Bibliothek verwenden.

Die MapStruct-Bibliothek wird für die Zuordnung zwischen Java-Bean-Typen verwendet . Durch die Verwendung eines benutzerdefinierten Mappers mit MapStruct können wir die Standardzuordnungsmethoden anpassen.

2. Maven-Abhängigkeiten

Fügen wir die mapstruct-Bibliothek in unsere Maven pom.xml ein :

 org.mapstruct mapstruct 1.3.1.Final 

Um die automatisch generierten Methoden innerhalb des Projekts sehen Zielordner , müssen wir die hinzufügen annotationProcessorPaths zum maven-Compiler-Plugin Plugin:

 org.apache.maven.plugins maven-compiler-plugin 3.5.1  1.8 1.8   org.mapstruct mapstruct 1.3.1.Final    

3. Benutzerdefinierter Mapper

Benutzerdefinierte Mapper werden verwendet, um bestimmte Konvertierungsanforderungen zu lösen. Um dies zu erreichen, müssen wir eine Methode für die Konvertierung definieren. Dann müssen wir MapStruct über die Methode informieren. Schließlich ruft MapStruct die Methode auf, um die Konvertierung von der Quelle zum Ziel durchzuführen.

Stellen wir uns zum Beispiel vor, wir haben eine App, die den Body Mass Index (BMI) des Benutzers berechnet. Um den BMI zu berechnen, müssen wir die Körperwerte des Benutzers erfassen. Um imperiale Einheiten in metrische Einheiten umzuwandeln, können wir die benutzerdefinierten Mapper-Methoden verwenden.

Es gibt zwei Möglichkeiten, einen benutzerdefinierten Mapper mit MapStruct zu verwenden. Wir können die benutzerdefinierte Methode entweder aufrufen, indem wir sie in die qualifizierteByName- Eigenschaft der @ Map- Annotation eingeben , oder wir können eine Annotation dafür erstellen.

Bevor wir beginnen, müssen wir eine DTO-Klasse definieren, die imperiale Werte enthält:

public class UserBodyImperialValuesDTO { private int inch; private int pound; // constructor, getters, and setters }

Als Nächstes definieren wir eine DTO-Klasse, die Metrikwerte enthält:

public class UserBodyValues { private double kilogram; private double centimeter; // constructor, getters, and setters }

3.1. Benutzerdefinierter Mapper mit Methode

Um benutzerdefinierte Mapper zu verwenden, erstellen wir eine Schnittstelle mit der Annotation @Mapper :

@Mapper public interface UserBodyValuesMapper { //... }

Zweitens erstellen wir unsere benutzerdefinierte Methode mit dem gewünschten Rückgabetyp und dem Argument, das wir konvertieren müssen. Wir müssen die Annotation @ Named mit dem Parameter value verwenden, um MapStruct über die benutzerdefinierte Mapper-Methode zu informieren:

@Mapper public interface UserBodyValuesMapper { @Named("inchToCentimeter") public static double inchToCentimeter(int inch) { return inch * 2.54; } //... }

Zum Schluss definieren wir die Mapper-Schnittstellenmethode mit der Annotation @Mapping . In dieser Anmerkung teilen wir MapStruct den Quelltyp, den Zieltyp und die verwendete Methode mit:

@Mapper public interface UserBodyValuesMapper { UserBodyValuesMapper INSTANCE = Mappers.getMapper(UserBodyValuesMapper.class); @Mapping(source = "inch", target = "centimeter", qualifiedByName = "inchToCentimeter") public UserBodyValues userBodyValuesMapper(UserBodyImperialValuesDTO dto); @Named("inchToCentimeter") public static double inchToCentimeter(int inch) { return inch * 2.54; } }

Testen wir unseren benutzerdefinierten Mapper:

UserBodyImperialValuesDTO dto = new UserBodyImperialValuesDTO(); dto.setInch(10); UserBodyValues obj = UserBodyValuesMapper.INSTANCE.userBodyValuesMapper(dto); assertNotNull(obj); assertEquals(25.4, obj.getCentimeter(), 0); 

3.2. Benutzerdefinierter Mapper mit einer Anmerkung

Um einen benutzerdefinierten Mapper mit einer Annotation zu verwenden, müssen Sie anstelle der Annotation @Named eine Annotation definieren. Anschließend müssen wir MapStruct über die neu erstellte Annotation informieren, indem wir den qualifiziertenByName- Parameter der @ Mapping- Annotation angeben .

Mal sehen, wie wir die Annotation definieren:

@Qualifier @Target(ElementType.METHOD) @Retention(RetentionPolicy.CLASS) public @interface PoundToKilogramMapper { }

Fügen wir unserer PfundToKilogram- Methode die Annotation @PoundToKilogramMapper hinzu :

@PoundToKilogramMapper public static double poundToKilogram(int pound) { return pound * 0.4535; } 

Definieren wir nun die Mapper-Schnittstellenmethode mit der Annotation @Mapping . In der Mapping-Annotation teilen wir MapStruct den Quelltyp, den Zieltyp und die Annotationsklasse mit, die verwendet werden sollen:

@Mapper public interface UserBodyValuesMapper { UserBodyValuesMapper INSTANCE = Mappers.getMapper(UserBodyValuesMapper.class); @Mapping(source = "pound", target = "kilogram", qualifiedBy = PoundToKilogramMapper.class) public UserBodyValues userBodyValuesMapper(UserBodyImperialValuesDTO dto); @PoundToKilogramMapper public static double poundToKilogram(int pound) { return pound * 0.4535; } }

Lassen Sie uns zum Schluss unseren benutzerdefinierten Mapper testen:

UserBodyImperialValuesDTO dto = new UserBodyImperialValuesDTO(); dto.setPound(100); UserBodyValues obj = UserBodyValuesMapper.INSTANCE.userBodyValuesMapper(dto); assertNotNull(obj); assertEquals(45.35, obj.getKilogram(), 0); 

4. Fazit

In diesem Artikel haben wir gelernt, wie Sie einen benutzerdefinierten Mapper mit der MapStruct-Bibliothek verwenden.

Die Implementierungen dieser Beispiele und Tests sind auf GitHub verfügbar.