Вступление
Как вы знаете, вы можете скопировать файл или папку из исходного расположения в местоположение назначения в любой операционной системе. Вы когда-нибудь задумывались о копировании 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:debadatta.mishra@gmail.com">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:debadatta.mishra@gmail.com">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 configurationlist.add("dozerMapping.xml");// Add to DozerMapperMapper 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:debadatta.mishra@gmail.com">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:debadatta.mishra@gmail.com">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. Загрузите полный проект и просмотрите исходный код, чтобы понять концепцию и ее использование. Исходя из сложности и дизайна, вы можете решить, следует ли использовать эту концепцию. По любым вопросам и ошибкам вы можете связаться со мной по адресу debadatta.mishra@gmail.com .
Ресурсы и ссылки
Существуют и другие доступные структуры, обеспечивающие более или менее манипулирование bean-компонентами. Я нашел каркас «Dozer», пригодный для различных целей. Существует также подобный вид фреймворка, называемый «Nomin», который обеспечивает сопоставление, аналогичное «Dozer», предоставляя конфигурацию в файле свойств. Я приведу ниже различные ссылки для ваших ссылок.