ModelMapper 一文读懂
Posted 在奋斗的大道
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ModelMapper 一文读懂相关的知识,希望对你有一定的参考价值。
目录
1、ModelMapper简介
ModelMapper是一个旨在简化对象映射框架,它根据约定处理对象之间的映射方式,为处理特定对象提供一个简单的、安全的、可重构安全API。
1.1 引入ModelMapper 的依赖
在pom.xml文件添加modelMapper相关依赖
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.4.2</version>
</dependency>
1.2 进行Mapping映射
使用ModelMapper来映射对象,主要分为以下两大类:
- Source model: 源数据对象
- Destination model:模板数据对象
1.3 ModelMapper 工作原理
在ModelMapper 调用map() 方法时,先分分析源对象和目标对象类型,根据匹配策略和其他配置确定那些属性需要进行隐式匹配,然后根据这些匹配映射数据。
即使源对象和目标对象的属性不同,ModelMapper 也会尽最大努力根据配置的匹配策略,将源对象和目标对象的属性进行匹配。
在实际项目开发过程中进行对象类型转换,经常出现如下操作:
- Controller层接受到客户端的DTO 对象,通过ModelMapper 框架将DTO对象转换为Service层可操作执行的BO对象。
- Service层调用Dao 层方法时,通过ModelMapper框架将BO对象转换为Dao 层可操作执行的PO对象。如果调用Dao 层有结果对象返回,又需要ModelMapper 框架将PO对象转换为BO对象进行返回。
- Controller层调用Service 层有对象返回,需要通过ModelMapper框架对象将BO对象转换为VO对象返回给客户端。
2、ModelMapper 基础操作
2.1 ModelMapper 基本映射
创建ModelMapper映射步骤总结:
1、添加ModelMapper 依赖Jar 包。
2、实例化ModelMapper类,调用map 方法,传入源对象和目标对象。
实战:创建Order和OrderDTO 类定义,通过ModelMapper实现Order类实例对象转换OrderDTO 类实例对象。
package com.zzg.modelmapper.po.source;
import lombok.Data;
@Data
public class Order
private Address address;
private Customer customer;
package com.zzg.modelmapper.po.source;
import lombok.Data;
@Data
public class Address
private String street;
private String city;
package com.zzg.modelmapper.po.source;
import lombok.Data;
@Data
public class Customer
private Name name;
package com.zzg.modelmapper.po.source;
import lombok.Data;
@Data
public class Name
private String firstName;
private String lastName;
package com.zzg.modelmapper.po.target;
import lombok.Data;
@Data
public class OrderDTO
private String customerFirstName;
private String customerLastName;
private String addressStreet;
private String addressCity;
测试:
package com.zzg.modelmapper.po.test;
import com.alibaba.fastjson.JSON;
import com.zzg.modelmapper.po.source.Address;
import com.zzg.modelmapper.po.source.Customer;
import com.zzg.modelmapper.po.source.Name;
import com.zzg.modelmapper.po.source.Order;
import com.zzg.modelmapper.po.target.OrderDTO;
import org.modelmapper.ModelMapper;
public class OneTest
public static void main(String[] args)
ModelMapper modelMapper = new ModelMapper();
Order order = new Order();
Customer customer = new Customer();
Name name = new Name();
name.setLastName("周");
name.setFirstName("程宇");
customer.setName(name);
Address address = new Address();
address.setCity("深圳");
address.setStreet("龙岗区横岗街道");
order.setCustomer(customer);
order.setAddress(address);
OrderDTO orderDTO = modelMapper.map(order, OrderDTO.class);
String jsonString = JSON.toJSONString(orderDTO);
System.out.println("jsonString = " + jsonString);
执行效果截图:
2.2 ModelMapper 集合转换
功能要求:将List<Order> 转换为List<OrderDTO>
功能实现:通过modelMapper.map(源对象Class, new TypeToken<List<目标读写Class>>() .getType());
测试:
Order order = new Order();
Customer customer = new Customer();
Name name = new Name();
name.setLastName("周");
name.setFirstName("程宇");
customer.setName(name);
Address address = new Address();
address.setCity("深圳");
address.setStreet("龙岗区横岗街道");
order.setCustomer(customer);
order.setAddress(address);
Order order2 = new Order();
Customer customer2 = new Customer();
Name name2 = new Name();
name2.setLastName("周");
name2.setFirstName("晨曦");
customer2.setName(name2);
Address address2 = new Address();
address2.setCity("深圳");
address2.setStreet("盐田区梅沙街道");
order2.setCustomer(customer2);
order2.setAddress(address2);
List<Order> containers = new ArrayList<>();
containers.add(order);
containers.add(order2);
ModelMapper modelMapper = new ModelMapper();
List<OrderDTO> orderDTOs = modelMapper.map(containers, new TypeToken<List<OrderDTO>>() .getType());
String jsonString = JSON.toJSONString(orderDTOs);
System.out.println("jsonString = " + jsonString);
执行效果截图:
2.3 ModelMapper 指定默认值
功能要求:Order类实例对象 转换OrderDTO 类实例对象时,将street属性值设置为:龙岗区横岗街道"。
功能实现:
public static void main(String[] args)
ModelMapper modelMapper = new ModelMapper();
Order order = new Order();
Customer customer = new Customer();
Name name = new Name();
name.setLastName("周");
name.setFirstName("程宇");
customer.setName(name);
Address address = new Address();
address.setCity("深圳");
address.setStreet("盐田区梅沙街道");
order.setCustomer(customer);
order.setAddress(address);
modelMapper.createTypeMap(Order.class, OrderDTO.class)
.addMappings(mapper-> mapper.using((Converter<String, String>) context ->
return "龙岗区横岗街道" ;
).map(it-> it.getAddress().getStreet(),OrderDTO::setAddressStreet));
OrderDTO orderDTO = modelMapper.map(order, OrderDTO.class);
String jsonString = JSON.toJSONString(orderDTO);
System.out.println("jsonString = " + jsonString);
执行效果截图:
2.4 ModelMapper 属性值转换
功能要求:OrderDTO类对象新增cityTest 和streetTest 属性,对应属性值为Order类实例对象Address 属性对象中的city 和street属性。
package com.zzg.modelmapper.po.target;
import lombok.Data;
@Data
public class OrderDTO
private String customerFirstName;
private String customerLastName;
private String addressStreet;
private String addressCity;
/**
* 新增属性
*/
private String cityTest;
private String streetTest;
测试:
public static void main(String[] args)
ModelMapper modelMapper = new ModelMapper();
Order order = new Order();
Customer customer = new Customer();
Name name = new Name();
name.setLastName("周");
name.setFirstName("程宇");
customer.setName(name);
Address address = new Address();
address.setCity("深圳");
address.setStreet("盐田区梅沙街道");
order.setCustomer(customer);
order.setAddress(address);
OrderDTO orderDTO =modelMapper.typeMap(Order.class, OrderDTO.class)
.addMappings(mapper->
// 自定义属性转换
mapper.map(src -> src.getAddress().getStreet(), OrderDTO::setStreetTest);
mapper.map(src -> src.getAddress().getCity(), OrderDTO::setCityTest);
).map(order);
String jsonString = JSON.toJSONString(orderDTO);
System.out.println("jsonString = " + jsonString);
执行效果截图:
拓展功能需求:OrderDTO 类对象新增枚举对象属性:OrderSource orderSource, 对应属性值为Order类实例对象新增字符串属性:String orderSource
package com.zzg.modelmapper.po.target;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public enum OrderSource
Mobile("1", "移动端"),
Web("2", "网页端"),
Other("3", "其他");
private String type;
private String message;
OrderSource()
OrderSource(String type, String message)
this.type = type;
this.message = message;
/**
* 枚举转Map
*/
private static Map<String, OrderSource> map = Stream.of(OrderSource.values()).collect(Collectors.toMap(OrderSource::getType, Function.identity(), (v1, v2) -> v1));
public static OrderSource getInstance(String type)
return map.get(type);
public String getType()
return type;
public void setType(String type)
this.type = type;
public String getMessage()
return message;
public void setMessage(String message)
this.message = message;
package com.zzg.modelmapper.po.target;
import lombok.Data;
@Data
public class OrderDTO
private String customerFirstName;
private String customerLastName;
private String addressStreet;
private String addressCity;
/**
* 新增属性
*/
private String cityTest;
private String streetTest;
private OrderSource orderSource;
package com.zzg.modelmapper.po.source;
import lombok.Data;
@Data
public class Order
private Address address;
private Customer customer;
/**
* 新增订单来源属性
*/
private String orderSource;
测试:
public static void main(String[] args)
ModelMapper modelMapper = new ModelMapper();
Order order = new Order();
Customer customer = new Customer();
Name name = new Name();
name.setLastName("周");
name.setFirstName("程宇");
customer.setName(name);
Address address = new Address();
address.setCity("深圳");
address.setStreet("盐田区梅沙街道");
order.setCustomer(customer);
order.setAddress(address);
order.setOrderSource("1");
OrderDTO orderDTO =modelMapper.typeMap(Order.class, OrderDTO.class)
.addMappings(mapper->
// 自定义属性转换
mapper.map(src -> src.getAddress().getStreet(), OrderDTO::setStreetTest);
mapper.map(src -> src.getAddress().getCity(), OrderDTO::setCityTest);
// 字符串转枚举
mapper.using((Converter<String, OrderSource>) context ->
return OrderSource.getInstance(context.getSource()) ;
).map(src -> src.getOrderSource(), OrderDTO::setOrderSource);
).map(order);
String jsonString = JSON.toJSONString(orderDTO);
System.out.println("jsonString = " + jsonString);
执行效果截图:
2.5 ModelMapper 属性值跳过
ModelMapper 隐式创建从源类型到目标类型中每个属性的映射,但有时可能需要跳过某些目标属性的映射。
功能要求:跳过OrderDTO类实例对象的addressStreet 和addressCity 属性值映射。
测试:
public static void main(String[] args)
ModelMapper modelMapper = new ModelMapper();
Order order = new Order();
Customer customer = new Customer();
Name name = new Name();
name.setLastName("周");
name.setFirstName("程宇");
customer.setName(name);
Address address = new Address();
address.setCity("深圳");
address.setStreet("盐田区梅沙街道");
order.setCustomer(customer);
order.setAddress(address);
order.setOrderSource("1");
OrderDTO orderDTO =modelMapper.typeMap(Order.class, OrderDTO.class)
.addMappings(mapper->
// 跳过属性
mapper.skip(OrderDTO::setAddressStreet);
mapper.skip(OrderDTO::setAddressCity);
// 自定义属性转换
mapper.map(src -> src.getAddress().getStreet(), OrderDTO::setStreetTest);
mapper.map(src -> src.getAddress().getCity(), OrderDTO::setCityTest);
// 字符串转枚举
mapper.using((Converter<String, OrderSource>) context ->
return OrderSource.getInstance(context.getSource()) ;
).map(src -> src.getOrderSource(), OrderDTO::setOrderSource);
).map(order);
String jsonString = JSON.toJSONString(orderDTO);
System.out.println("jsonString = " + jsonString);
执行效果截图:
2.6 ModelMapper 条件映射
ModelMapper 提供Condition条件接口,判断是否执行源属性到模板属性映射。
功能要求:在Order类中添加订单金额字段:amount, 在OrderDTO 类中添加订单金额字段:amount和订单优先级字段priority,如果金额大于1000, priority 设置为最高基本=3,其他设置为普通基本=2。
public static void main(String[] args)
ModelMapper modelMapper = new ModelMapper();
Order order = new Order();
Customer customer = new Customer();
Name name = new Name();
name.setLastName("周");
name.setFirstName("程宇");
customer.setName(name);
Address address = new Address();
address.setCity("深圳");
address.setStreet("盐田区梅沙街道");
order.setCustomer(customer);
order.setAddress(address);
order.setOrderSource("1");
order.setAmount(100000);
OrderDTO orderDTO =modelMapper.typeMap(Order.class, OrderDTO.class)
.addMappings(mapper->
// 添加判断条件 + 添加自定义转换条件
mapper.when((Condition<Integer, String>) context -> context.getSource() > 0).using((Converter<Integer, String>) context ->
return context.getSource() >=1000 ? "3":"2" ;
).map(it-> it.getAmount(),OrderDTO::setPriority);
// 自定义属性转换
mapper.map(src -> src.getAddress().getStreet(), OrderDTO::setStreetTest);
mapper.map(src -> src.getAddress().getCity(), OrderDTO::setCityTest);
// 字符串转枚举
mapper.using((Converter<String, OrderSource>) context ->
return OrderSource.getInstance(context.getSource()) ;
).map(src -> src.getOrderSource(), OrderDTO::setOrderSource);
).map(order);
String jsonString = JSON.toJSONString(orderDTO);
System.out.println("jsonString = " + jsonString);
订单金额大于10000,执行效果截图:
订单金额小于10000,执行效果截图:
拓展功能:如果没有设置订单金额,将priority 设置为异常订单=1。
测试:
public static void main(String[] args)
ModelMapper modelMapper = new ModelMapper();
Order order = new Order();
Customer customer = new Customer();
Name name = new Name();
name.setLastName("周");
name.setFirstName("程宇");
customer.setName(name);
Address address = new Address();
address.setCity("深圳");
address.setStreet("盐田区梅沙街道");
order.setCustomer(customer);
order.setAddress(address);
order.setOrderSource("1");
OrderDTO orderDTO =modelMapper.typeMap(Order.class, OrderDTO.class)
.addMappings(mapper->
// 添加判断条件 + 添加自定义转换条件
mapper.when((Condition<Integer, String>) context ->
if(context.getSource() != null && context.getSource()> 0)
return true;
return false;
).using((Converter<Integer, String>) context ->
return context.getSource() >=1000 ? "3":"2" ;
).map(it-> it.getAmount(),OrderDTO::setPriority);
// 自定义属性转换
mapper.map(src -> src.getAddress().getStreet(), OrderDTO::setStreetTest);
mapper.map(src -> src.getAddress().getCity(), OrderDTO::setCityTest);
// 字符串转枚举
mapper.using((Converter<String, OrderSource>) context ->
return OrderSource.getInstance(context.getSource()) ;
).map(src -> src.getOrderSource(), OrderDTO::setOrderSource);
).map(order);
String jsonString = JSON.toJSONString(orderDTO);
System.out.println("jsonString = " + jsonString);
订单金额无,执行效果截图:
结果:由于没有设置订单金额,导致OrderDTO 类对象中的 priority 属性字段没有对应 映射,这与我们提出的功能要求不符,需要添加以下业务逻辑处理:
如果订单金额为空 或者为0,需要将OrderDTO 类对象中的 priority 属性字段映射为1(异常订单类型)
public static void main(String[] args)
ModelMapper modelMapper = new ModelMapper();
Order order = new Order();
Customer customer = new Customer();
Name name = new Name();
name.setLastName("周");
name.setFirstName("程宇");
customer.setName(name);
Address address = new Address();
address.setCity("深圳");
address.setStreet("盐田区梅沙街道");
order.setCustomer(customer);
order.setAddress(address);
order.setOrderSource("1");
OrderDTO orderDTO =modelMapper.typeMap(Order.class, OrderDTO.class)
.addMappings(mapper->
// 添加判断条件 + 添加自定义转换条件
mapper.when((Condition<Integer, String>) context ->
if(context.getSource() != null && context.getSource()> 0)
return true;
return false;
).using((Converter<Integer, String>) context ->
return context.getSource() >=1000 ? "3":"2" ;
).map(it-> it.getAmount(),OrderDTO::setPriority);
// 添加判空添加 + 添加默认值
mapper.when((Condition<Integer, ?>) condition ->
if(condition.getSource() == null || condition.getSource() == 0)
return true;
return false;
).using((Converter<Integer, String>) converter->
return "1";
).map(it-> it.getAmount(),OrderDTO::setPriority);
// 自定义属性转换
mapper.map(src -> src.getAddress().getStreet(), OrderDTO::setStreetTest);
mapper.map(src -> src.getAddress().getCity(), OrderDTO::setCityTest);
// 字符串转枚举
mapper.using((Converter<String, OrderSource>) context ->
return OrderSource.getInstance(context.getSource()) ;
).map(src -> src.getOrderSource(), OrderDTO::setOrderSource);
).map(order);
String jsonString = JSON.toJSONString(orderDTO);
System.out.println("jsonString = " + jsonString);
订单金额无,执行效果截图:
2.7 ModelMapper 转换
转换器允许在将源映射到目标属性时进行自定义转换。ModelMapper 提供Converter转换接口,实现源映射到目标属性时自定义转换。
示例代码片段:
// 字符串转枚举
mapper.using((Converter<String, OrderSource>) context ->
return OrderSource.getInstance(context.getSource()) ;
).map(src -> src.getOrderSource(), OrderDTO::setOrderSource);
2.8 ModelMapper 提供者
ModelMapper 提供Provide接口,返回源属性到模板属性映射值。
功能要求:Order 类属性amount 为null, 设置OrderDTO 类属性amount = 0
测试:
public static void main(String[] args)
ModelMapper modelMapper = new ModelMapper();
Order order = new Order();
Customer customer = new Customer();
Name name = new Name();
name.setLastName("周");
name.setFirstName("程宇");
customer.setName(name);
Address address = new Address();
address.setCity("深圳");
address.setStreet("盐田区梅沙街道");
order.setCustomer(customer);
order.setAddress(address);
order.setOrderSource("1");
OrderDTO orderDTO =modelMapper.typeMap(Order.class, OrderDTO.class)
.addMappings(mapper->
// 添加判断条件 + 添加自定义转换条件
mapper.when((Condition<Integer, String>) context ->
if(context.getSource() != null && context.getSource()> 0)
return true;
return false;
).using((Converter<Integer, String>) context ->
return context.getSource() >=1000 ? "3":"2" ;
).map(it-> it.getAmount(),OrderDTO::setPriority);
// 添加判空添加 + 添加默认值
mapper.when((Condition<Integer, ?>) condition ->
if(condition.getSource() == null || condition.getSource() == 0)
return true;
return false;
).using((Converter<Integer, String>) converter->
return "1";
).map(it-> it.getAmount(),OrderDTO::setPriority);
// 通过Provider 设置默认值
mapper.with((Provider<Integer>) provider ->
return 0;
).map(it-> it.getAmount(),OrderDTO::setAmount);
// 自定义属性转换
mapper.map(src -> src.getAddress().getStreet(), OrderDTO::setStreetTest);
mapper.map(src -> src.getAddress().getCity(), OrderDTO::setCityTest);
// 字符串转枚举
mapper.using((Converter<String, OrderSource>) context ->
return OrderSource.getInstance(context.getSource()) ;
).map(src -> src.getOrderSource(), OrderDTO::setOrderSource);
).map(order);
String jsonString = JSON.toJSONString(orderDTO);
System.out.println("jsonString = " + jsonString);
效果展示:
以上是关于ModelMapper 一文读懂的主要内容,如果未能解决你的问题,请参考以下文章