由于dozer不再维护,公司内部的项目需要从dozer转移到mapstruct,自学了一下mapstruct的使用方法。
mapstruct简介
mapstruct与传统的复制 javabean 的工具不同(比如dozer),并不提供javabean转换的方法,他只是个代码生成的工具,会自动将javabean转换的方法生成到本地,从而在代码中直接调用生成的方法,避免了反射的使用,一定程度上提高了性能
mapstruct是编译时的工具,与dozer等运行时的工具相比,在程序运行时不会调用mapstruct本身,而是使用mapstruct编译时生成的代码,从而可以进行debug,并且由于是编译时就已经生成的代码,可以在编译时发现错误。
但是与dozer等相比,mapstruct需要自动生成代码,是编译时的工具,需要在编译时就指定转换前和转换后的bean的类的类型,不能像dozer等一样的使用泛型和object来实现任意类型的bean转换
在eclipse中使用mapstruct
介绍在eclipse中的maven工程里使用mapstruct
使用其他工具可以参照官网教程 https://mapstruct.org/documentation/installation/
1.添加依赖
在pom.xml中加入以下代码
...
<properties>
<org.mapstruct.version>1.5.3.final</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> <!-- depending on your project -->
<target>1.8</target> <!-- depending on your project -->
<annotationprocessorpaths>
<path>
<groupid>org.mapstruct</groupid>
<artifactid>mapstruct-processor</artifactid>
<version>${org.mapstruct.version}</version>
</path>
<!-- other annotation processors -->
</annotationprocessorpaths>
</configuration>
</plugin>
</plugins>
</build>
2.安装自动处理注解的工具(eclipse - m2e-apt)
如果不安装,将不会自动生成代码,可以通过mvn命令手动编译来生成本地代码,但是这样不会实时修改生成的代码,建议安装m2e-apt
安装方法:打开eclipse - help - eclipse marketplace
搜索m2e-apt 按下install
安装完后在工程的pom.xml的properties继续中加入以下代码
<properties>
...
<!-- automatically run annotation processors within the incremental compilation -->
<m2e.apt.activation>jdt_apt</m2e.apt.activation>
...
</properties>
示例
经过上述步骤已经可以在工程内使用mapstruct了
1.引入mapstruct 首先要创建一个mapstruct的接口
创建一个接口,并加上@mapper注解,这样一个mapstruct接口就做好了
import org.mapstruct.mapper;
@mapper
public interface mymapstruct {
}
查看target/generated-sources/annotations目录下,生成了接口的实现类
打开可以看到自动生成的代码
2.接下来定义需要转换的bean类
public class dto01 {
private string field01;
private string field02;
public string getfield01() {
return field01;
}
public void setfield01(string field01) {
this.field01 = field01;
}
public string getfield02() {
return field02;
}
public void setfield02(string field02) {
this.field02 = field02;
}
}
public class dto02 {
private string field01;
private string field02;
public string getfield01() {
return field01;
}
public void setfield01(string field01) {
this.field01 = field01;
}
public string getfield02() {
return field02;
}
public void setfield02(string field02) {
this.field02 = field02;
}
}
3.在接口中定义转换方法
只需要定义方法的返回类型 名字和参数即可,mapstruct会自动生成实现方法
方法名是任意的,自己起名即可
import org.mapstruct.mapper;
@mapper
public interface mymapstruct {
dto01 dto02_to_dto01(dto02 dto02);
}
查看target/generated-sources/annotations目录下的实现类
mapstruct自动生成了转换方法,实际上也是基于set get方法来实现的,简单易读
4.调用方法
首先实例化对象,然后像普通方法一样通过对象调用即可
实例化方法
mymapstruct mymapstruct = mappers.getmapper(mymapstruct.class);
如果使用spring等框架来管理bean,也可以使用inject注解来实例化
@inject
mymapstruct mymapstruct;
测试:
import org.mapstruct.factory.mappers;
public class mapstructtest {
public static void main(string[] args) {
dto02 dto02 = new dto02();
dto02.setfield01("01");
dto02.setfield02("02");
//实例化
mymapstruct mymapstruct = mappers.getmapper(mymapstruct.class);
dto01 dto01 = mymapstruct.dto02_to_dto01(dto02);
system.out.println(dto01.getfield01());
system.out.println(dto01.getfield02());
}
}
成功将dto02的值复制给了dto01
5.自定义转换方法
如果不想使用mapstruct自动生成的方法也可以在接口中自定义
可以使用default 关键字,并自己添加方法体来实现,必须要return
import org.mapstruct.mapper;
@mapper
public interface mymapstruct {
dto01 dto02_to_dto01(dto02 dto02);
default dto01 mymethod(dto02 dto02){
dto01 dto01 = new dto01();
dto01.setfield01(dto02.getfield01() + "my1");
dto01.setfield02(dto02.getfield02() + "my2");
return dto01;
}
}
6.自定义某个字段的转换
如果bean中的字段需要特殊的转换,也可以自己来实现
例如
将dto01中的field01 修改为boolean类型
dto02中的field01 修改为 int类型
public class dto01 {
private boolean field01;
private string field02;
public boolean isfield01() {
return field01;
}
public void setfield01(boolean field01) {
this.field01 = field01;
}
public string getfield02() {
return field02;
}
public void setfield02(string field02) {
this.field02 = field02;
}
}
public class dto02 {
private int field01;
private string field02;
public int getfield01() {
return field01;
}
public void setfield01(int field01) {
this.field01 = field01;
}
public string getfield02() {
return field02;
}
public void setfield02(string field02) {
this.field02 = field02;
}
}
这时候接口在报错
can’t map property “int field01” to “boolean field01”. consider to declare/implement a mapping method: “boolean map(int value)”.
由于int无法转换成boolean ,mapstruct无法自动生成代码,所以需要自己来定义该字段的转换
首先定义自己的转换逻辑方法,并加上@named注解,定义一个别名
注意:是这个包下的named org.mapstruct.named
@named("toboolean")
default boolean inttoboolean(int value) {
if (value >0) {
return true;
}else {
return false;
}
}
然后在转换方法上使用@mapping注解,target = 需要转换的字段名 qualifiedbyname = 自定义的转换方法别名(@named上定义的)
@mapping(target = "field01", qualifiedbyname = "toboolean")
dto01 dto02_to_dto01(dto02 dto02);
import org.mapstruct.mapper;
import org.mapstruct.mapping;
import org.mapstruct.named;
@mapper
public interface mymapstruct {
@mapping(target = "field01", qualifiedbyname = "toboolean")
dto01 dto02_to_dto01(dto02 dto02);
@named("toboolean")
default boolean inttoboolean(int value) {
if (value >0) {
return true;
}else {
return false;
}
}
}
这样的话两个bean的field01字段就会按照自定义的逻辑来转换了
发表评论