Вступление
Как вы знаете, вы можете скопировать файл или папку из исходного расположения в местоположение назначения в любой операционной системе. Вы когда-нибудь задумывались о копировании Java-объекта, который по сути является POJO? Есть много случаев, когда вам нужно скопировать содержимое исходного компонента в целевой компонент. Я не имею в виду конструктор копирования, мелкое или глубокое копирование или клонирование объекта. В некоторых случаях вам необходимо скопировать содержимое исходного компонента в пункт назначения с условиями фильтрации или без них. Для этого может быть n причин, и есть много способов, как этого добиться. В этом небольшом посте я познакомлю вас с фреймворком под названием «Dozer», чтобы реализовать эту функциональность самым простым и надежным способом.
Технические детали
Эта небольшая статья предоставит вам утилиту Dozer для копирования исходного бина в целевой бин. Прежде чем мы начнем, давайте подумаем о ситуации, когда у вас есть исходный компонент, который содержит много полей, а исходный компонент принадлежит другому проекту или модулю. Теперь вы хотите представить бин внешнему миру как часть разработки REST-службы вашего веб-сервиса. Это не рекомендуется делать это. Могут быть следующие причины.
- Исходная система не позволяет делать это из-за нарушения безопасности.
- Исходный бин не сериализован и является финальным классом.
- Исходный бин имеет много полей; некоторые из них не обязательны.
- Исходный компонент очень тяжелый и содержит много вложенных компонентов.
- У исходного компонента есть поля разных типов, которые могут не требоваться для другой системы.
Выше могут быть некоторые другие конкретные причины, подумайте о ситуации, вы хотите сделать вызов REST или вызов веб-службы, чтобы получить минимальные данные учетной записи человека. Но в исходной системе есть компонент «AccountBean», который содержит много конфиденциальной информации, такой как пароль интернет-банка, пароль профиля, номер панорамирования или номер социального страхования, общий баланс и т. Д. Вы хотите разработать приложение, в котором вы хотите предоставить только адрес учетной записи. реквизиты, название и домашний филиал банка. Это обязательная ситуация, когда вы хотите, чтобы ваш пользовательский бин был открыт для внешнего использования на основе номера счета. В этом случае вы должны скопировать оригинальный компонент в ваш пользовательский компонент. Для достижения этой функциональности вы можете сделать это следующими способами.
- Напишите код, чтобы вручную скопировать содержимое исходного компонента в целевой компонент.
- Используйте утилиту java Reflection или Introspection для копирования из исходного объекта в целевой.
- Используйте доступный фреймворк, который делает копию автоматически.
В этом случае мы узнаем о платформе, которая помогает нам копировать содержимое исходного компонента в целевой компонент. Фреймворк под названием «Dozer» очень популярен и гибок в использовании и интеграции в приложение. Вы найдете больше документации по Dozer на различных интернет-сайтах. В этом посте я предоставлю вам очень простое и практичное использование Dozer.
Давайте быстро изучим использование Dozer в следующих сценариях.
- Скопировать исходный простой / плоский боб в пункт назначения Обычный / плоский боб
- Копировать коллекции
- Двунаправленная копия бобов
- Скопируйте плоский боб в вложенный боб и наоборот
- Скопируйте боб с пользовательским преобразованием.
Скопировать исходный простой / плоский боб в пункт назначения Обычный / плоский боб
Это самый простой случай, когда у нас есть исходный POJO, и мы хотим скопировать в целевой POJO. Давайте рассмотрим следующий код Java.
Структура источника POJO ниже.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package com.ddlab.rnd.type1.srcpkg; /** * The Class Person is used as a source bean for Person which contains Address * object. * * @author <a href="mailto:[email protected]">Debadatta Mishra</a> * @since 2013 */ public class Person { /** The name. */ private String name; /** The age. */ private int age; /** The adrs. */ private Address adrs; // All getter and setter method below } |
Структура назначения POJO ниже.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package com.ddlab.rnd.type1.destnpkg; /** * The Class Person1 is used as destination bean for Person1 which contains * Addrss1 object * * @author <a href="mailto:[email protected]">Debadatta Mishra</a> * @since 2013 */ public class Person1 { /** The name1. */ private String name1; /** The age1. */ private int age1; /** The adrs1. */ private Address1 adrs1; //All getter setter method below } |
Давайте посмотрим файл сопоставления dozer с названием «dozerMapping.xml»
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
|
<? xml version = "1.0" encoding = "UTF-8" ?> < mappings xmlns = "http://dozer.sourceforge.net" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://dozer.sourceforge.net http://dozer.sourceforge.net/schema/beanmapping.xsd" > < mapping map-id = "a" > < class-a >com.ddlab.rnd.type1.srcpkg.Person</ class-a > < class-b >com.ddlab.rnd.type1.destnpkg.Person1</ class-b > < field > < a >name</ a > < b >name1</ b > </ field > < field > < a >age</ a > < b >age1</ b > </ field > < field > < a >adrs.doorNo</ a > < b >adrs1.doorNo1</ b > </ field > < field > < a >adrs.stName</ a > < b >adrs1.stName1</ b > </ field > </ mapping > </ mappings > |
Приведенный выше файл конфигурации xml выглядит очень интуитивно понятным, поскольку <class-a> относится к исходному компоненту, а <class-b> относится к целевому компоненту. Другое поле <a> ссылается на свойство исходного компонента, а <b> ссылается на свойство целевого компонента.
Давайте посмотрим на окончательный код, который выполняет отображение бинов.
1
2
3
4
5
6
|
List<String> list = new ArrayList<String>(); // Add the mapping configuration list.add( "dozerMapping.xml" ); // Add to DozerMapper Mapper mapper = new DozerBeanMapper(list); mapper.map(p, p1, "a" ); |
Теперь все готово, выглядит очень просто и предоставляет множество мощных функций. Вы помните следующие несколько вещей для копирования bean-компонентов с использованием платформы Dozer.
- Исходный боб
- Целевой бин
- Конфигурация файла сопоставления Dozer
- Конфигурация отображения должна содержать исходный класс POJO с правильным именем пакета
- Конфигурация отображения должна содержать целевой класс POJO с правильным именем пакета
- Конфигурация отображения должна иметь правильное точное имя свойства, которое вы определили в классе java
Конфигурация сопоставления обеспечивает следующие преимущества.
- Вы можете изменить имя свойства по мере необходимости, и оно не требует сборки приложения.
- Вы можете добавить свойство в класс Java, как и при необходимости.
- Вы можете иметь один или несколько файлов свойств для конкретных требований.
- Вы можете редактировать и удалять сопоставление по мере необходимости.
- Вы также можете настроить отображение в приложении Spring, то есть в файле конфигурации Spring.
Копировать коллекции
Есть определенные случаи, когда вы хотите скопировать список типа источника в список типа назначения. Список может содержать различные типы объектов. Давайте посмотрим типичный код 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
|
package com.ddlab.dozer.type2.srcpkg; import java.util.List; /** * The Class AddressList is used as a source List object which contains object * of type Address. * * @author <a href="mailto:[email protected]">Debadatta Mishra</a> * @since 2013 */ public class AddressList { /** The adrs list. */ private List<Address> adrsList; /** * Gets the adrs list. * * @return the adrs list */ public List<Address> getAdrsList() { return adrsList; } /** * Sets the adrs list. * * @param adrsList * the new adrs list */ public void setAdrsList(List<Address> adrsList) { this .adrsList = adrsList; } } |
В приведенном выше случае список содержит список объектов типа Address. Давайте узнаем, как достичь.
Прежде всего создайте отображение между объектами Address из источника в место назначения, а затем создайте отображение между списком источника и списком назначения. Давайте посмотрим файл конфигурации сопоставления.
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
|
<? xml version = "1.0" encoding = "UTF-8" ?> xsi:schemaLocation = "http://dozer.sourceforge.net http://dozer.sourceforge.net/schema/beanmapping.xsd" > < mapping map-id = "k" > < class-a >com.ddlab.dozer.type2.srcpkg.Address</ class-a > < class-b >com.ddlab.dozer.type2.destnpkg.AddressBean</ class-b > < field > < a >name</ a > < b >name</ b > </ field > < field > < a >id</ a > < b >id</ b > </ field > </ mapping > < mapping map-id = "q1" type = "one-way" relationship-type = "non-cumulative" > < class-a >com.ddlab.dozer.type2.srcpkg.AddressList</ class-a > < class-b >com.ddlab.dozer.type2.destnpkg.AddressBeanList</ class-b > < field map-id = "k" > < a >adrsList</ a > < b >adrsList</ b > </ field > </ mapping > </ mappings > |
Чтобы скопировать объект списка, вы можете использовать тот же код, что и в первом случае.
Двунаправленная копия бобов
В этом случае вам нужно иметь отображение, которое выполняет копирование бина в обоих направлениях. Давайте подумаем о ситуации, когда вы хотите преобразовать внутренний Java-бин в пользовательский EJB-компонент для предоставления в качестве веб-службы, и, наконец, вы получаете данные в EJB-компоненте и конвертируете их во внутренний EJB-компонент. Не рекомендуется писать еще одно сопоставление. «Dozer» предоставляет атрибуты в конфигурации сопоставления xml для копирования в обоих направлениях в зависимости от требований. Я предоставляю атрибут, необходимый для упоминания в конфигурации бульдозера.
1
2
3
|
< mapping map-id = "k" type = "bi-directional" > <!-- Other field mapping --> </ mapping > |
Приведенный выше тип атрибута ( type="bi-directional"
) обеспечивает гибкость копирования объектов в обоих направлениях.
Скопируйте плоский боб в вложенный боб и наоборот
В зависимости от требований проекта у вас может быть сложный компонент, содержащий вложенные другие компоненты 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
|
<? xml version = "1.0" encoding = "UTF-8" ?> xsi:schemaLocation = "http://dozer.sourceforge.net http://dozer.sourceforge.net/schema/beanmapping.xsd" > < mapping map-id = "a" > < class-a >com.ddlab.dozer.type4.srcpkg.MyPerson</ class-a > < class-b >com.ddlab.dozer.type4.destnpkg.Person1</ class-b > <!-- Other field info --> < field > < a >doorNo</ a > < b >adrs1.doorNo1</ b > </ field > < field > < a >stName</ a > < b >adrs1.stName1</ b > </ field > < field > < a >cname</ a > < b >adrs1.country.name</ b > </ field > < field > < a >ccode</ a > < b >adrs1.country.code</ b > </ field > < field > < a >fd</ a > < b >adrs1.country.bd</ b > </ field > </ mapping > </ mappings > |
В приведенном выше случае отметьте линию красным цветом. Чтобы получить практический пример, обратитесь к следующему файлу конфигурации сопоставления.
- flat2NestedBeanMapping.xml
- nestedBeanMapping2Flat.xml
Обратитесь к следующим пакетам для этого.
- com.ddlab.dozer.type4.destnpkg
- com.ddlab.dozer.type4.srcpkg
Вы можете скачать полный проект Eclipse по следующей ссылке: https://www.dropbox.com/s/j6ep7wq7lalfe2k/dozerbeancopy.zip
Скопируйте боб с пользовательским преобразованием.
Это очень типичное и сложное состояние, которое возникает во время разработки. Представьте, что у вас есть Java-бин, который содержит определенные поля, такие как дата в API JodaTime, объект типа UUID, поле типа BigInteger и т. Д., И у вас есть Java-бин со всеми полями примитивного типа. В этом случае вы должны использовать пользовательские конвертеры и вставить их в файл конфигурации отображения «Dozer», чтобы «Dozer» автоматически копировал 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
|
<? xml version = "1.0" encoding = "UTF-8" ?> < mappings xmlns = "http://dozer.sourceforge.net" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://dozer.sourceforge.net http://dozer.sourceforge.net/schema/beanmapping.xsd" > < configuration > < custom-converters > < converter type = "com.ddlab.dozer.type5.converters.Date2JodaDateConverter" > < class-a >org.joda.time.LocalDate</ class-a > < class-b >java.util.Date</ class-b > </ converter > </ custom-converters > </ configuration > < mapping map-id = "k" type = "bi-directional" > < class-a >com.ddlab.dozer.type5.srcpkg.SrcBean</ class-a > < class-b >com.ddlab.dozer.type5.destnpkg.DestnBean</ class-b > <!-- For UUID --> < field copy-by-reference = "true" > < a >idKey</ a > < b >uid</ b > </ field > <!-- For java.util.Date to org.joda.time.LocalDate --> < field > < a >utilDate</ a > < b >jodaDate</ b > </ field > <!-- For double to java.math.BigDecimal --> < field > < a >amount</ a > < b >bigDecimal</ b > </ field > </ mapping > </ mappings > |
Dozer предоставляет интерфейс под названием « org.dozer.CustomConverter », который позволяет выполнять пользовательские преобразования в соответствии с нашими требованиями. Ниже приведен небольшой фрагмент кода.
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
|
package com.ddlab.dozer.type5.converters; import org.dozer.CustomConverter; import org.dozer.MappingException; import org.joda.time.LocalDate; /** * The Class Date2JodaDateConverter is used as a Dozer custom converter for * converting java.util.Date to Jodatime LocalDate. * * @author <a href="mailto:[email protected]">Debadatta Mishra</a> * @since 2013 */ public class Date2JodaDateConverter implements CustomConverter { /* * (non-Javadoc) * * @see org.dozer.CustomConverter#convert(java.lang.Object, * java.lang.Object, java.lang.Class, java.lang.Class) */ @Override public Object convert(Object existingDestinationFieldValue, Object sourceFieldValue, @SuppressWarnings ( "rawtypes" ) Class destinationClass, @SuppressWarnings ( "rawtypes" ) Class sourceClass) { if (sourceFieldValue == null ) { return null ; } if (sourceFieldValue instanceof java.util.Date) { java.util.Date utilDate = (java.util.Date) sourceFieldValue; LocalDate localDate = new LocalDate(utilDate.getTime()); return localDate; } throw new MappingException( "Misconfigured/unsupported mapping" ); } } |
Чтобы узнать больше о ссылках на следующие пакеты.
- com.ddlab.dozer.type5.converters
- com.ddlab.dozer.type5.destnpkg
- com.ddlab.dozer.type5.srcpkg
Как сделать
Для работы с каркасом «Dozer» вы должны использовать следующие jar-файлы в вашем classpath.
- Викисклада BeanUtils-1.7.jar
- Обще-Ланг-2.4.jar
- Обще-каротаж 1.1.1.jar
- Обще-каротаж апи-1.1.1.jar
- бульдозер-5.3.2.jar
- Joda-времени 2.2.jar
- log4j-1.2.16.jar
- log4j-над-SLF4J-1.6.1.jar
- SLF4J-апи-1.6.1.jar
- SLF4J-jdk14-1.6.1.jar
- SLF4J-простой 1.6.1.jar
Вы должны скачать фреймворк «Dozer» по следующей ссылке: http://dozer.sourceforge.net/ . Dozer также предоставляет плагин Eclipse для облегчения работы с картами.
Связанные пакеты и файл конфигурации
Простая фасоль в обычную фасоль
- com.ddlab.rnd.type1.destnpkg (из источника)
- com.ddlab.rnd.type1.srcpkg (из src)
- com.ddlab.rnd.type1 (из теста)
- dozerMapping.xml (Конфигурация сопоставления)
Копии коллекций
- com.ddlab.dozer.type2.destnpkg (из src)
- com.ddlab.dozer.type2.srcpkg (из источника)
- com.ddlab.dozer.type2 (из теста)
- list2ListMapping.xml (Конфигурация сопоставления)
Двунаправленная копия Боба
- com.ddlab.dozer.type3 (из теста)
- dozerBidirectionalMapping1.xml (Конфигурация сопоставления)
Плоская Вложенная Боб / Вложенная Боб в Плоскую Боб
- com.ddlab.dozer.type4.destnpkg (из источника)
- com.ddlab.dozer.type4.srcpkg (из src)
- com.ddlab.dozer.type4 (из теста)
- flat2NestedBeanMapping.xml (Конфигурация сопоставления)
- nestedBeanMapping2Flat.xml (Конфигурация сопоставления)
Пользовательский Конвертер
- com.ddlab.dozer.type5.converters (из источника)
- com.ddlab.dozer.type5.destnpkg (из источника)
- com.ddlab.dozer.type5.srcpkg (из источника)
- com.ddlab.dozer.type5 (из теста)
- dozercustomconvertermapping.xml
Скачать
Вы можете скачать полный проект eclipse со следующего сайта dropbox: https://www.dropbox.com/s/j6ep7wq7lalfe2k/dozerbeancopy.zip . Вы можете легко настроить Eclipse IDE, импортировав проект.
Вывод
Надеюсь, вам понравился мой небольшой пост об использовании инфраструктуры Dozer для копирования компонентов в Java. Загрузите полный проект и просмотрите исходный код, чтобы понять концепцию и ее использование. Исходя из сложности и дизайна, вы можете решить, следует ли использовать эту концепцию. По любым вопросам и ошибкам вы можете связаться со мной по адресу [email protected] .
Ресурсы и ссылки
Существуют и другие доступные структуры, обеспечивающие более или менее манипулирование bean-компонентами. Я нашел каркас «Dozer», пригодный для различных целей. Существует также подобный вид фреймворка, называемый «Nomin», который обеспечивает сопоставление, аналогичное «Dozer», предоставляя конфигурацию в файле свойств. Я приведу ниже различные ссылки для ваших ссылок.