Dozer是Java Bean到Java Bean的映射器,它以递归的方式将数据从一个对象复制到另一个对象。通常,这些Java Bean将具有不同的复杂类型。它支持简单属性映射,复杂类型映射,双向映射,隐式显式映射,以及递归映射。这包括映射需要在元素层面上进行映射的集合属性。可以将Dozer用作两个对象之间属性转换的工具,使用它可以很方便地对项目中的DO、DTO、VO进行相互转换。
本文主要对SpringBoot2.x集成Dozer及其基本使用进行简单总结,其中SpringBoot使用的2.4.5
版本。
一、引入依赖
<dependency>
<groupId>com.github.dozermapper</groupId>
<artifactId>dozer-spring-boot-starter</artifactId>
<version>6.5.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- lombok插件 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
二、实体类
User类:
package com.rtxtitanv.model;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
@Accessors(chain = true)
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String gender;
private String email;
private Date birthday;
}
UserDTO类:
package com.rtxtitanv.model;
import lombok.Data;
import lombok.experimental.Accessors;
@Accessors(chain = true)
@Data
public class UserDTO {
private Long userId;
private String userName;
private Integer userAge;
private String gender;
private String email;
private String birthday;
}
三、编写配置文件
resources/dozer/
目录下创建Dozer的全局配置文件global-dozer.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://dozermapper.github.io/schema/bean-mapping"
xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mapping
http://dozermapper.github.io/schema/bean-mapping.xsd">
<!-- 全局配置:<date-format>表示日期格式 -->
<configuration>
<date-format>yyyy/MM/dd HH:mm:ss</date-format>
</configuration>
</mappings>
resources/dozer/
目录下创建Dozer的映射文件dozer.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://dozermapper.github.io/schema/bean-mapping"
xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mapping
http://dozermapper.github.io/schema/bean-mapping.xsd">
<!-- 描述两个类中属性的对应关系,对于两个类中同名的属性可以不映射 -->
<mapping date-format="yyyy/MM/dd HH:mm:ss">
<class-a>com.rtxtitanv.model.User</class-a>
<class-b>com.rtxtitanv.model.UserDTO</class-b>
<field>
<a>id</a>
<b>userId</b>
</field>
<field>
<a>name</a>
<b>userName</b>
</field>
<field>
<a>age</a>
<b>userAge</b>
</field>
</mapping>
</mappings>
resources
目录下创建application.yml
配置文件:
dozer:
# 指定Dozer的映射配置文件位置
mapping-files:
- classpath:dozer/global-dozer.xml
- classpath:dozer/dozer.xml
四、创建测试类
创建单元测试类DozerTest
:
package com.rtxtitanv;
import com.github.dozermapper.core.Mapper;
import com.rtxtitanv.model.*;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
@Slf4j
@SpringBootTest
class DozerTest {
@Resource
private Mapper mapper;
@Test
void test1() {
UserDTO userDTO = new UserDTO();
userDTO.setUserId(1L).setUserName("ZhaoYun").setGender("男").setUserAge(20).setEmail("zhaoyun@xxx.com")
.setBirthday("2001/8/18 18:05:32");
User user = mapper.map(userDTO, User.class);
log.info(user.toString());
UserDTO userDTO2 = mapper.map(user, UserDTO.class);
log.info(userDTO2.toString());
}
}
执行测试方法,发现User和UserDTO相互转换成功:
五、Dozer的基本使用
下面对Dozer的一些基本使用进行总结。Dozer支持注解、API、XML三种映射配置方式,XML方式比较常用,前面使用的也是XML映射配置方式。XML映射配置中mapping
元素的map-id
属性可以设置该映射的标识,通过此标识来确定使用该映射关系。
在dozer.xml
中新增以下配置:
<!-- map-id:映射的标识,通过此标识来确定使用该映射关系 -->
<mapping date-format="yyyy/MM/dd HH:mm:ss" map-id="user">
<class-a>com.rtxtitanv.model.User</class-a>
<class-b>com.rtxtitanv.model.UserDTO</class-b>
<field>
<a>id</a>
<b>userId</b>
</field>
<field>
<a>name</a>
<b>userName</b>
</field>
<field>
<a>age</a>
<b>userAge</b>
</field>
</mapping>
新增以下测试方法:
@Test
void test2() {
UserDTO userDTO = new UserDTO();
userDTO.setUserId(2L).setUserName("MaChao").setGender("男").setUserAge(21).setEmail("machao@xxx.com")
.setBirthday("2000/6/15 08:45:20");
User user = mapper.map(userDTO, User.class, "user");
log.info(user.toString());
}
执行测试方法,发现转换成功:
在调用map
方法时也可以直接指定要转换的目标对象。新增以下测试方法:
@Test
void test3() {
UserDTO userDTO = new UserDTO();
userDTO.setUserId(3L).setUserName("LiuBei").setGender("男").setUserAge(30).setEmail("liubei@xxx.com")
.setBirthday("1991/1/20 13:36:55");
User user = new User();
mapper.map(userDTO, user, "user");
log.info(user.toString());
}
执行测试方法,发现转换成功:
通过field-exclude
标签可以设置不想进行转换的属性,这些属性在进行转换时会被自动排除。
在dozer.xml
中新增以下配置:
<mapping date-format="yyyy/MM/dd HH:mm:ss" map-id="user-exclude">
<class-a>com.rtxtitanv.model.User</class-a>
<class-b>com.rtxtitanv.model.UserDTO</class-b>
<field>
<a>id</a>
<b>userId</b>
</field>
<field>
<a>name</a>
<b>userName</b>
</field>
<field>
<a>age</a>
<b>userAge</b>
</field>
<field-exclude>
<a>email</a>
<b>email</b>
</field-exclude>
</mapping>
新增以下测试方法:
@Test
void test4() {
UserDTO userDTO = new UserDTO();
userDTO.setUserId(1L).setUserName("ZhaoYun").setGender("男").setUserAge(20).setEmail("zhaoyun@xxx.com")
.setBirthday("2001/8/18 18:05:32");
User user = mapper.map(userDTO, User.class, "user-exclude");
log.info(user.toString());
}
执行测试方法,发现email属性被成功排除:
Dozer中的映射方式默认都是双向映射,如果想让转换不可逆,即只需要单向转换,可以设置mapping
元素的type
属性为one-way
来开启单向映射。
在dozer.xml
中新增以下配置:
<!-- type="one-way"将映射设置为单向映射 -->
<mapping date-format="yyyy/MM/dd HH:mm:ss" map-id="user-oneway" type="one-way">
<class-a>com.rtxtitanv.model.UserDTO</class-a>
<class-b>com.rtxtitanv.model.User</class-b>
<field>
<a>userId</a>
<b>id</b>
</field>
<field>
<a>userName</a>
<b>name</b>
</field>
<field>
<a>userAge</a>
<b>age</b>
</field>
</mapping>
新增以下测试方法:
@Test
void test5() {
UserDTO userDTO = new UserDTO();
userDTO.setUserId(1L).setUserName("ZhaoYun").setGender("男").setUserAge(20).setEmail("zhaoyun@xxx.com")
.setBirthday("2001/8/18 18:05:32");
User user = mapper.map(userDTO, User.class, "user-oneway");
log.info(user.toString());
UserDTO userDTO2 = mapper.map(user, UserDTO.class, "user-oneway");
log.info(userDTO2.toString());
}
执行测试方法,发现只有UserDTO转换为User成功:
当两个实体类中都嵌套有能够互相转换的实体类型属性时,也可以进行相互转换。
创建Order类:
package com.rtxtitanv.model;
import lombok.Data;
import lombok.experimental.Accessors;
@Accessors(chain = true)
@Data
public class Order {
private Long id;
private String number;
private String description;
private User user;
}
创建OrderDTO类:
package com.rtxtitanv.model;
import lombok.Data;
import lombok.experimental.Accessors;
@Accessors(chain = true)
@Data
public class OrderDTO {
private Long orderId;
private String orderNumber;
private String orderDescription;
private UserDTO userDTO;
}
在dozer.xml
中新增以下配置:
<mapping date-format="yyyy/MM/dd HH:mm:ss" map-id="order">
<class-a>com.rtxtitanv.model.Order</class-a>
<class-b>com.rtxtitanv.model.OrderDTO</class-b>
<field>
<a>id</a>
<b>orderId</b>
</field>
<field>
<a>number</a>
<b>orderNumber</b>
</field>
<field>
<a>description</a>
<b>orderDescription</b>
</field>
<field>
<a>user</a>
<b>userDTO</b>
</field>
</mapping>
新增以下测试方法:
@Test
void test6() {
OrderDTO orderDTO = new OrderDTO();
UserDTO userDTO = new UserDTO().setUserId(6L).setUserName("DiaoChan").setGender("女").setUserAge(18)
.setEmail("diaochan@xxx.com").setBirthday("2003/12/27 23:10:36");
orderDTO.setOrderId(1L).setOrderNumber("78956328").setOrderDescription("二两麻辣牛肉面").setUserDTO(userDTO);
Order order = mapper.map(orderDTO, Order.class, "order");
log.info(order.toString());
OrderDTO orderDTO2 = mapper.map(order, OrderDTO.class, "order");
log.info(orderDTO2.toString());
}
执行测试方法,发现Order和OrderDTO相互转换成功:
Dozer还可以对深层属性进行映射,即深度映射。例如一个对象中的String类型属性可以与另一个对象中嵌套的对象的属性进行映射。
创建UserInfo类:
package com.rtxtitanv.model;
import lombok.Data;
import lombok.experimental.Accessors;
@Accessors(chain = true)
@Data
public class UserInfo {
private String gender;
private String email;
private String birthday;
}
创建UserInfoDTO类:
package com.rtxtitanv.model;
import lombok.Data;
import lombok.experimental.Accessors;
@Accessors(chain = true)
@Data
public class UserInfoDTO {
private Long userId;
private String userName;
private Integer userAge;
private UserInfo userInfo;
}
在dozer.xml
中新增以下配置:
<mapping date-format="yyyy/MM/dd HH:mm:ss" map-id="user-deep-mapping">
<class-a>com.rtxtitanv.model.UserInfoDTO</class-a>
<class-b>com.rtxtitanv.model.User</class-b>
<field>
<a>userId</a>
<b>id</b>
</field>
<field>
<a>userName</a>
<b>name</b>
</field>
<field>
<a>userAge</a>
<b>age</b>
</field>
<field>
<a>userInfo.gender</a>
<b>gender</b>
</field>
<field>
<a>userInfo.email</a>
<b>email</b>
</field>
<field>
<a>userInfo.birthday</a>
<b>birthday</b>
</field>
</mapping>
新增以下测试方法:
@Test
void test7() {
UserInfo userInfo = new UserInfo();
userInfo.setGender("男").setEmail("zhaoyun@xxx.com").setBirthday("2001/8/18 18:05:32");
UserInfoDTO userInfoDTO = new UserInfoDTO();
userInfoDTO.setUserId(1L).setUserName("ZhaoYun").setUserAge(20).setUserInfo(userInfo);
User user = mapper.map(userInfoDTO, User.class, "user-deep-mapping");
log.info(user.toString());
}
执行测试方法,发现UserInfoDTO成功转换为User:
Dozer还支持注解方式配置映射,使用@Mapping
注解可以进行一些简单的映射处理。
创建UserEntity类:
package com.rtxtitanv.model;
import com.github.dozermapper.core.Mapping;
import lombok.Data;
import lombok.experimental.Accessors;
@Accessors(chain = true)
@Data
public class UserEntity {
@Mapping(value = "userId")
private Long id;
@Mapping(value = "userName")
private String name;
@Mapping(value = "userAge")
private Integer age;
private String gender;
private String email;
private String birthday;
}
@Mapping
只需要在源类中指定目标类中对应的属性即可。
创建UserVO类:
package com.rtxtitanv.model;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
@Accessors(chain = true)
@Data
public class UserVO {
private Long userId;
private String userName;
private Integer userAge;
private String gender;
private String email;
private Date birthday;
}
新增以下测试方法:
@Test
void test8() {
UserEntity userEntity = new UserEntity();
userEntity.setId(1L).setName("ZhaoYun").setGender("男").setAge(20).setEmail("zhaoyun@xxx.com")
.setBirthday("2001/8/18 18:05:32");
UserVO userVO = mapper.map(userEntity, UserVO.class);
log.info(userVO.toString());
}
执行测试方法,发现转换成功:
代码示例
Github:https://github.com/RtxTitanV/springboot-learning/tree/master/springboot2.x-learning/springboot-dozer
Gitee:https://gitee.com/RtxTitanV/springboot-learning/tree/master/springboot2.x-learning/springboot-dozer
到此这篇关于SpringBoot2.x 集成 Dozer的文章就介绍到这了,更多相关SpringBoot2.x 集成 Dozer内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!