网站首页 > java教程 正文
做java开发的程序员相信都读过阿里版的开发规范,可能还不只读一次,是反反复复的读那种,在阿里开发规范有这么一节应用分层。从显示层->web请求处理层->service业务逻辑层->manger通用业务处理层->dao数据持久层,上层依赖下层这么一个工程结构,这也是目前大多数企业开发使用的工程分层,每个公司大同小异。
同时为了层与层之间的解耦,也会有对应的分层领域模型,前端到web层用VO对象,显示层到Service层用DTO对象,Service层到dao数据层用DO对象,虽然这种领域分层的思想能带来层与层之间的逻辑解耦,让每层专注于自己的核心职责和逻辑,避免所有代码写在一起像一团乱麻一样,提升了代码的可读性和可维护性,但同样也带来另一个问题,层与层之间为了解耦,定义了太多的领域对象模型,对象模型之间需要进行转换,开发的成本直线上升,那么有没有办法能减少这块的工作呢?答案是肯定的。
对象转换的几种方法
一、get/set赋值方式:这种一般用于对象属性较少,如果碰到对象属性多的情况,就很容易眼花缭乱,一不小心就写错了,耗时耗力先不说,同时也会带来整个代码段非常的臃肿,几十上百行都是在get/set。
二、Apache BeanUtils:直接用apache的工具类BeanUtils.copyProperties进行对象拷贝,但使用了很多反射,做了很多校验,所以导致性能较差,一般用在对性能要求不太高的业务中去使用,如果你是使用了spring 框架,也可以使用Spring 自带的BeanUtils.copyProperties,在性能方面比它要好些,去掉了一些不必要的校验以及增加了一些缓存的机制,加快了转换的速度。
三、MapStruct:它是基于编译时的一个框架,在编译期间就将代码进行生成class文件,所以和我们使用get/set 方法的性能是一致的。
当然还有一些不是很常用的转换方法,比如通过JSON的方式进行转换,通过基于cglib的动态代理BeanCopier的方式进行转换等等。
MapStruct
一、如何使用?
拿官方的使用文档的说明作为例子
第一步:引入jar包,目前最新版本是1.6.2版本,因为是编译时生成class文件,所以还需要引入maven plugin
...
<properties>
<org.mapstruct.version>1.6.2</org.mapstruct.version>
</properties>
...
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
</dependencies>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
...
第二步:准备好两个需要进行转换的对象
public class Car {
private String make;
private int numberOfSeats;
private CarType type;
//constructor, getters, setters etc.
}
public class CarDto {
private String make;
private int seatCount;
private String type;
//constructor, getters, setters etc.
}
第三步:定义转移的mapper类,如果原对象属性和目标对象属性不一致,可以使用mapping进行字段映射,一致的话就不需要进行映射了。
@Mapper
public interface CarMapper {
CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );
@Mapping(source = "numberOfSeats", target = "seatCount")
CarDto carToCarDto(Car car);
}
一个简单的对象之间的转换就完成了,是不是so easy。
当然针对于一些复杂的属性转换,也可以自己自定义转换类,详细可以参考mapstrut的官方使用文档https://mapstruct.org/documentation/stable/reference/html
二、MapStruct避坑误区
对象属性转换的坑
1、MapStruct能够帮助我们在一些类型之间进行自动转换,比如Long 映射成为Integer,这个时候就会出现当Long的数值超过Integer的最大值,出现值溢出的现象
2、对于一些日期的转换,Mapstruct进行时间格式化时,采用的是默认时区UTC,这就会导致时间出现问题。
要避免此类问题,尽量避免出现原对象的属性类型与目标对象的属性一致,实在要进行转换,需要查看MapStruct生成后的源码情况时什么。
.....
和Lombok共用的坑
如果我们对象使用 Lombok 的话,使用 @Mapping指定不同字段名,编译期间可能会报错,这是因为Lombok 也是编译期时自动生成代码,这两者可能导致冲突,当 MapStruct 生成代码时,还不存在 Lombok 生成的代码。
解决这类问题的方法,就是maven plugin增加lombok。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
当然mapstrut使用还有很多其他的误区,要避免在使用过程尽量不犯错或者是少犯错,建议多看下它编译后生成的源码文件,毕竟自动生成的代码也有可能存在问题,通过查看这些代码,也可以帮助我们了解mapstrut是如何映射的,有助于我们发现问题解决问题。
猜你喜欢
- 2024-10-03 SpringBoot中如何根据JSON数据生成一个动态对象?
- 2024-10-03 边玩手机边学Java----Java基础之Map
- 2024-10-03 Java Stream API:优雅地操作Map(java map stream filter)
- 2024-10-03 聊聊Mybatis的初始化之Mapper.xml映射文件的解析
- 2024-10-03 MapStruct 使用教程, 万字详解(mapstruct enum)
- 2024-10-03 看似简单,在JAVA中如何将一个Object转换成Array
- 2024-10-03 java8函数式Map操作也太强大了吧,1次就帮我省了10多行代码
- 2024-10-03 map的一个骚操作!你学废了么?#互联网
- 2024-10-03 轻松搞定!用JavaScript将列表转换为Map
- 2024-10-03 告别 BeanUtils,拥抱 MapStruct:高效 Java 对象映射的经典之选
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)