MapStruct使用

在一个项目的不同模块或不同需求中,经常需要一个数据模型的一部分,需要进行对象与对象之间的互相转换。

最为简单直接的就是使用getter,setter方法进行转换,或者使用自定义Beans.copyProperties等实现。

前者编写麻烦,后者使用反射的方式导致性能消耗较大

MapStruct是一个属性映射工具、框架。通过生成这些繁琐的代码来节省时间。

依赖

以SpringBoot+Lombok+MapStruct为例,其余场景见 GitHub示例代码

...
<properties>
    <org.mapstruct.version>1.5.2.Final</org.mapstruct.version>
    <org.projectlombok.version>1.18.20</org.projectlombok.version>
    <lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version>
</properties>
...
<dependencies>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>
    <!-- lombok dependencies should not end up on classpath -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>${org.projectlombok.version}</version>
        <scope>provided</scope>
    </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>
                    <!-- MapStruct 注解处理器 -->
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${org.mapstruct.version}</version>
                    </path>
                    <!-- Lombok 注解处理器 -->
                    <path>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok</artifactId>
                        <version>${org.projectlombok.version}</version>
                    </path>
                    <!-- MapStruct 和 Lombok 注解绑定处理器 -->
                    <path>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok-mapstruct-binding</artifactId>
                        <version>${lombok-mapstruct-binding.version}</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>
...

使用

创建pojo

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Boy {
    private String name;
    private Integer age;
    private String school;
    private String blog;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Man {
    private String name;
    private Integer age;
    private String work;
    private String blogName;
    private String blogUrl;
}
  1. 公共属性:name,age
  2. Boy独有属性:school
  3. Man独有属性:work
  4. 不同名属性:blog / blogName
  5. 自定义转换:blogUrl

创建映射器

配置
属性
  • mapstruct.suppressGeneratorTimestamp

    • 禁止在生成的映射器中创建时间戳
    • 默认false
  • mapstruct.supppressGeneratorVersionInfoComment

    • 禁止在生成的映射器中创建属性
    • 默认为false
  • mapstruct.defaultComponentModel

    • 基于生成映射器的组件模型的名称,支持default,cdi, spring, jsr30
    • 默认default,使用spring可以使用@Autowired方式注入
  • mapstruct.unmappedTargetPolicy

    • 在未使用source值填充映射方法的target属性的情况下要应用的默认报告策略,支持ERROR(映射代码生成失败)、WARN(构建时引起警告)、IGNORE(忽略)
      • 默认为WARN,如Warning:(36, 24) java: Unmapped target property: .....
配置方式一:注解配置
@Mapper(componentModel="spring", ....)
配置方式二:pom配置
<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>
                <compilerArgs>
                    <compilerArg>
                        -Amapstruct.suppressGeneratorTimestamp=true
                    </compilerArg>
                    <compilerArg>
                        -Amapstruct.suppressGeneratorVersionInfoComment=true
                    </compilerArg>
                </compilerArgs>
            </configuration>
        </plugin>
    </plugins>
</build>
映射器实现
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

@Mapper
public  Interface ObjectConvertor(){
    
    @Mapping(source = "blogName", target = "blog")
    @Mapping(source = "blogName", target = "blogUrl", qualifiedByName = "blogUrl")
    Man boy2Man(Boy boy);

    @Named("blogUrl")
    default String blogUrl(String blog){
        return "https://"+blog;
    }
}
  1. 属性的默认转换是按照属性名进行转换

  2. List等对象需要先有其中元素对象的转换方法。

  3. 自定义的转换方式采用qualifiedName@Named()实现

  4. @Mappingsource可以是传入的参数,如@Mapping(source=“boy”, ...)

  5. 对于多个不同名属性,可以在@Mapping外包一层@Mappings,或多个@Mapping叠加

    @Mappings({
        @Mapping(source = "blogName", target = "blog"),
        ...
    })
    
  6. 由于生成的代码直接为.class文件,如果是对pojo的属性做出调整,重新运行时不会再重新生成,导致类型转换出错,需要ReBuild。

使用

@Autowired
ObjectConvertor objectConvertor;

public void objConvert() {
    Boy boy = new Boy("zang", 18, "zjut", "zang.gold");
    System.out.println(boy);
    Man man = objectConvertor.boy2Student(boy);
    System.out.println("After convert: ");
    System.out.println(man);
}
~$: Boy(name=zang, age=18, school=zjut, blog=zang.gold)
~$: After convert: 
~$: Man(name=zang, age=18, work=null, blogName=zang.gold)
posted @   Zang998  阅读(64)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示