Перейти к основному содержимому

Пользовательский картограф с MapStruct

· 4 мин. чтения

1. Обзор

В этой статье мы узнаем, как использовать собственный маппер с библиотекой MapStruct .

Библиотека MapStruct используется для отображения между типами компонентов Java . Используя пользовательский сопоставитель с MapStruct , мы можем настроить методы сопоставления по умолчанию.

2. Зависимости Maven

Давайте добавим библиотеку mapstruct в наш Maven pom.xml :

<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.3.1.Final</version>
</dependency>

Чтобы увидеть автоматически сгенерированные методы внутри целевой папки проекта , мы должны добавить annotationProcessorPaths в плагин maven-compiler- plugin:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.3.1.Final</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>

3. Пользовательский картограф

Пользовательские преобразователи используются для решения конкретных требований преобразования. Чтобы достичь этого, мы должны определить метод для преобразования. Затем мы должны уведомить MapStruct о методе. Наконец, MapStruct вызовет метод для преобразования исходного объекта в целевой.

Например, давайте представим, что у нас есть приложение, которое вычисляет отчет об индексе массы тела (ИМТ) пользователя. Чтобы рассчитать ИМТ, мы должны собрать значения тела пользователя. Чтобы преобразовать имперские единицы в метрические, мы можем использовать пользовательские методы сопоставления.

Есть два способа использования пользовательского картографа с MapStruct. Мы можем либо вызвать пользовательский метод, введя его в свойствеqualifiedByName аннотации @Mapping , либо создать для него аннотацию. ``

Прежде чем мы начнем, мы должны определить класс DTO для хранения имперских значений:

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

Далее давайте определим класс DTO для хранения значений метрик:

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

3.1. Пользовательский картограф с методом

Чтобы начать использовать собственные карты, давайте создадим интерфейс с аннотацией @Mapper :

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

Во-вторых, давайте создадим наш пользовательский метод с типом возвращаемого значения, который мы хотим, и аргументом, который нам нужно преобразовать. Мы должны использовать аннотацию @ Named с параметром value, чтобы сообщить MapStruct о пользовательском методе сопоставления:

@Mapper
public interface UserBodyValuesMapper {

@Named("inchToCentimeter")
public static double inchToCentimeter(int inch) {
return inch * 2.54;
}

//...
}

И, наконец, давайте определим метод интерфейса картографа с помощью аннотации @Mapping . В этой аннотации мы сообщим MapStruct о типе источника, типе цели и методе, который он будет использовать:

@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;
}
}

Давайте протестируем наш пользовательский маппер:

UserBodyImperialValuesDTO dto = new UserBodyImperialValuesDTO();
dto.setInch(10);

UserBodyValues obj = UserBodyValuesMapper.INSTANCE.userBodyValuesMapper(dto);

assertNotNull(obj);
assertEquals(25.4, obj.getCentimeter(), 0);

3.2. Пользовательский картограф с аннотацией

Чтобы использовать пользовательский преобразователь с аннотацией, мы должны определить аннотацию вместо аннотации @Named . Затем мы должны сообщить MapStruct о вновь созданной аннотации, указав параметрqualByName аннотации @Mapping .

Давайте посмотрим, как мы определяем аннотацию:

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

Давайте добавим аннотацию @PoundToKilogramMapper к нашему методу poundToKilogram :

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

Теперь давайте определим метод интерфейса картографа с помощью аннотации @Mapping . В аннотации сопоставления мы сообщим MapStruct об исходном типе, целевом типе и классе аннотации, который он будет использовать:

@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;
}
}

Наконец, давайте протестируем наш пользовательский картограф:

UserBodyImperialValuesDTO dto = new UserBodyImperialValuesDTO();
dto.setPound(100);

UserBodyValues obj = UserBodyValuesMapper.INSTANCE.userBodyValuesMapper(dto);

assertNotNull(obj);
assertEquals(45.35, obj.getKilogram(), 0);

4. Вывод

В этой статье мы узнали, как использовать пользовательский преобразователь с библиотекой MapStruct.

Реализации этих примеров и тестов доступны на GitHub .