Преобразование данных из одной формы в другую является широко используемой концепцией в ИТ-индустрии. MapStruct позволяет преобразовывать bean-компоненты на основе аннотаций, генерируя реализацию mapper во время компиляции. Это гарантирует, что во время выполнения не будет проблем с производительностью.
Что такое MapStruct?
MapStruct — это генератор кода, который значительно упрощает реализацию отображений между типами Java-бинов на основе соглашения о конфигурации.
Сгенерированный код отображения использует простые вызовы методов и поэтому быстр, безопасен для типов и прост для понимания.
Почему MapStruct?
Многоуровневые приложения часто требуют отображения между различными объектными моделями (например, объектами и DTO). Написание такого кода отображения является утомительной и подверженной ошибкам задачей. MapStruct стремится упростить эту работу, максимально автоматизируя ее.
В отличие от других структур отображения MapStruct генерирует отображения компонентов во время компиляции, что обеспечивает высокую производительность, обеспечивает быструю обратную связь с разработчиком и тщательную проверку ошибок.
Реализация
pom.xml
В web.xml добавьте « maven-compiler-plugin » и с идентификатором группы « org.apache.maven.plugins «. Вы можете добавить конкретную исходную / целевую версию jdk и получить последнюю доступную версию с
Сайт MapStruct .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.6</source> <!-- or higher, depending on your project --> <target>1.6</target> <!-- or higher, depending on your project --> <annotationProcessorPaths> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.1.0.Beta1</version> </path> </annotationProcessorPaths> </configuration></plugin> |
Теперь добавьте jar mapstruct в качестве зависимости.
|
1
2
3
4
5
|
<dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>1.1.0.Beta1</version></dependency> |
Постановка проблемы и решение
Предположим, у нас есть два pojos, представляющих личные и деловые контакты, как указано ниже, и мы используем оба на конкретных jsps. Теперь для функциональности, где оба контакта одинаковы, нам нужно передавать данные из одного pojo в другое.
PrimaryContact.java
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
public class PrimaryContact { private String name; private String phone; private String email; public PrimaryContact() { super(); } public PrimaryContact(String name, String phone, String email) { super(); this.name = name; this.phone = phone; this.email = email; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "PrimaryContact [name=" + name + ", phone=" + phone + ", email=" + email + "]"; }} |
BusinessContact.java
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
public class BusinessContact { private String firstName; private String lastName; private String businessPhone; private String businessEmail; private String businessCountry; public BusinessContact() { super(); } public BusinessContact(String firstName, String lastName, String businessPhone, String businessEmail, String businessCountry) { super(); this.firstName = firstName; this.lastName = lastName; this.businessPhone = businessPhone; this.businessEmail = businessEmail; this.businessCountry = businessCountry; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getBusinessPhone() { return businessPhone; } public void setBusinessPhone(String businessPhone) { this.businessPhone = businessPhone; } public String getBusinessEmail() { return businessEmail; } public void setBusinessEmail(String businessEmail) { this.businessEmail = businessEmail; } public String getBusinessCountry() { return businessCountry; } public void setBusinessCountry(String businessCountry) { this.businessCountry = businessCountry; } @Override public String toString() { return "BusinessContact [firstName=" + firstName + ", lastName=" + lastName + ", businessPhone=" + businessPhone + ", businessEmail=" + businessEmail + ", businessCountry=" + businessCountry + "]"; }} |
Мы пишем Mapper для передачи данных, как показано ниже. Аннотация @Mappings определяет, какие атрибуты из исходного pojo будут переданы конкретному атрибуту в целевом pojo. Аннотация определяет, что обратное отображение @InheritInverseConfiguration должно быть выполнено.
ContactMapper.java
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
/** * @author javareferencegv */@Mapper@DecoratedWith(ContactMapperDecorator.class)public interface ContactMapper { ContactMapper INSTANCE = Mappers.getMapper(ContactMapper.class); /** * We define only those mappings which doesn't have same signature in source and target */ @Mappings({ @Mapping(source = "phone", target = "businessPhone"), @Mapping(source = "email", target = "businessEmail"), @Mapping(target = "businessCountry", constant="USA") }) BusinessContact primaryToBusinessContact(PrimaryContact primary); @InheritInverseConfiguration PrimaryContact businessToPrimaryContact(BusinessContact business); } |
Будут сценарии, в которых сопоставление не является прямым, и нам нужна настраиваемая логика перед сопоставлением одного атрибута с другим. Одним из таких примеров здесь является то, что основной контакт имеет полное имя, а деловой контакт — имя и фамилия. В таком сценарии мы используем Decorator для добавления пользовательской реализации. Это определенная аннотация @Decorated с добавлением в маппер. Реализация для декоратора выглядит следующим образом:
ContactMapperDecorator.java
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public abstract class ContactMapperDecorator implements ContactMapper{ private final ContactMapper delegate; public ContactMapperDecorator(ContactMapper delegate) { this.delegate = delegate; } @Override public BusinessContact primaryToBusinessContact(PrimaryContact primary){ BusinessContact business = delegate.primaryToBusinessContact(primary); //Executes the mapper String[] names = primary.getName().split(" "); business.setFirstName(names[0]); business.setLastName(names[1]); return business; } @Override public PrimaryContact businessToPrimaryContact(BusinessContact business){ PrimaryContact primary = delegate.businessToPrimaryContact(business); //Executes the mapper primary.setName(business.getFirstName() + " " + business.getLastName()); return primary; } } |
Исполнение:
После того, как мы создадим файл класса реализации, будет сгенерирован mapstruct. Мы все настроены на запуск картографа.
|
01
02
03
04
05
06
07
08
09
10
11
|
public class ContactConvertor { public static void main(String[] args) { PrimaryContact primary = new PrimaryContact("Jack Sparrow","9999999999","test@javareferencegv.com"); BusinessContact business = ContactMapper.INSTANCE.primaryToBusinessContact(primary); System.out.println(business); PrimaryContact primaryConverted = ContactMapper.INSTANCE.businessToPrimaryContact(business); System.out.println(primaryConverted); }} |
Выход :
|
1
2
|
BusinessContact [firstName=Jack, lastName=Sparrow, businessPhone=9999999999, businessEmail=test@javareferencegv.com, businessCountry=USA]PrimaryContact [name=Jack Sparrow, phone=9999999999, email=test@javareferencegv.com] |
| Ссылка: | MapStruct: передача данных из одного компонента в другой от нашего партнера JCG Гаурава Варма в блоге Java Reference . |