在springboot3.4.4和jdk17环境下集成使用mapstruct
在springboot3.4.4和jdk17环境下集成使用mapstruct
MapStruct可以减少编码量,dto,entity相互转换时,自动生成set,get方法的调用。
源码地址:https://gitcode.com/qq_39339588/mapstruct.git2025-04-21
一、maven依赖
<properties><java.version>17</java.version><maven.compiler.source>${java.version}</maven.compiler.source><maven.compiler.target>${java.version}</maven.compiler.target><org.projectlombok.version>1.18.16</org.projectlombok.version><org.mapstruct.version>1.6.3</org.mapstruct.version></properties>
<!--mapStruct依赖-->
<!-- mapstruct -->
<dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct</artifactId><version>${org.mapstruct.version}</version>
</dependency>
<!-- lombok dependency should not end up on classpath -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${org.projectlombok.version}</version><scope>provided</scope>
</dependency><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>${java.version}</source><target>${java.version}</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><!-- additional annotation processor required as of Lombok 1.18.16 --><path><groupId>org.projectlombok</groupId><artifactId>lombok-mapstruct-binding</artifactId><version>0.2.0</version></path></annotationProcessorPaths></configuration></plugin></plugins></build>
建议安装插件 mapstruct support,按 ctrl + 鼠标左键 ,会跳转到参数对应的类
二、准备实体类
package space.goldchen.mapstruct.entity;import lombok.Data;
import lombok.Getter;
import lombok.Setter;/*** 对象1* @author 2021* @create 2025-04-18 16:41*/
@Data
public class Pig {/*** id*/private Long id;/*** 姓名*/private String name;/*** 年龄*/private Integer age;/*** 价格*/private Double price;
}
package space.goldchen.mapstruct.entity;import lombok.Data;/*** @author 2021* @create 2025-04-18 16:50*/
@Data
public class Person {private Long id;private String name;
}
三、准备DTO
package space.goldchen.mapstruct.dto;import lombok.Data;/*** @author 2021* @create 2025-04-18 16:44*/
@Data
public class PigDto {private Long id;private String name;private Integer age;
}
package space.goldchen.mapstruct.dto;import lombok.Data;/*** @author 2021* @create 2025-04-18 16:46*/
@Data
public class PersonDto {private Long idid;private String namename;private String fullName;
}
四、创建Mapper映射
1. 创建公用接口
package space.goldchen.mapstruct.mapper;/*** @author 2021* @create 2025-04-21 09:17*/import java.util.List;/*** 转换对象的属性名称一致时,可以省略Mappings的对应关系设置,使用泛型比较合适* mapstruct 公共类* <DTO,Entity>*/
public interface BaseMapper<D, E> {/*** entity转 DTO** @param entity* @return*/D toDto(E entity);/*** DTO 转 entity** @param dto* @return*/E toEntity(D dto);/*** entity集合 转 DTO集合** @param entityList* @return*/List<D> toDto(List<E> entityList);/*** DTO集合 转 entity集合** @param dtoList* @return*/List<E> toEntity(List<D> dtoList);
}
2. 创建PigDtoMapper映射关系
@Mapper(componentModel = “spring”,unmappedTargetPolicy = ReportingPolicy.IGNORE)
package space.goldchen.mapstruct.mapper;import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.ReportingPolicy;
import space.goldchen.mapstruct.dto.PigDto;
import space.goldchen.mapstruct.entity.Pig;/*** @author 2021* @create 2025-04-18 16:52*/
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface PigDtoMapper extends BaseMapper<PigDto,Pig> {/*** pig转为pigDto* @param pig* @return*/@Mappings({// 属性名称一致时,可以省略@Mapping(source = "id", target = "id"),@Mapping(source = "name", target = "name"),@Mapping(source = "age", target = "age")})public PigDto toDto(Pig pig);}
3. 创建PersonMapper映射关系
package space.goldchen.mapstruct.mapper;import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.ReportingPolicy;
import space.goldchen.mapstruct.dto.PersonDto;
import space.goldchen.mapstruct.entity.Person;/*** @author 2021* @create 2025-04-21 11:24*/
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface PersonMapper extends BaseMapper<PersonDto, Person>{@Mappings({// 属性名称一致时,可以省略@Mapping(source = "id", target = "idid"),@Mapping(source = "name", target = "namename"),@Mapping(source = "name", target = "fullName")})@OverridePersonDto toDto(Person entity);
}
五、调用测试
package space.goldchen.mapstruct;import ch.qos.logback.classic.Logger;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import space.goldchen.mapstruct.dto.PersonDto;
import space.goldchen.mapstruct.dto.PigDto;
import space.goldchen.mapstruct.entity.Person;
import space.goldchen.mapstruct.entity.Pig;
import space.goldchen.mapstruct.mapper.PersonMapper;
import space.goldchen.mapstruct.mapper.PigDtoMapper;@SpringBootTest
@Slf4j
class MapStructApplicationTests {@Resourceprivate PigDtoMapper pigDtoMapper;@Resourceprivate PersonMapper personMapper;@DisplayName("测试Pig转PigDto")@Testvoid testPigDtoMapper() {Pig pig = new Pig();pig.setId(1L);pig.setName("pig");pig.setAge(2);pig.setPrice(100.0);PigDto pigDto = pigDtoMapper.toDto(pig);log.info("pigDto:{}", pigDto);}@DisplayName("测试Person转PersonDto")@Testvoid testPersonToPersonDto () {Person person = new Person();person.setId(2L);person.setName("我是personName");PersonDto personDto = personMapper.toDto(person);log.info("personDto:{}", personDto);}}
七、更多细节
1. 设置默认值
@Mapping(source = "person.name",target = "personName",defaultValue = "默认值")
2. 使用表达式
// 目前java是唯一受支持的语言,达式必须以Java表达式的形式给出
// 注意: 这个属性不能与source()、defaultValue()、defaultExpression()、qualifiedBy()、qualifiedByName()或constant()一起使用。
@Mapping(target = "describe", source = "describe", defaultValue = "默认值")
@Mapping(target = "createTime",expression = "java(new java.util.Date())")
PersonDTO conver(Person person);
@Mapping(target = "created",expression = "java(cn.hutool.core.date.DateTime.now())")
3. 类中的子类转换
// uses 成员类,子类
@Mapper(componentModel = "spring", uses = {Log3InnerMapper.class},unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface Log3Mapper extends BaseMapper<Log3DTO, Log3> {}
4. Map的转换
// MapMapping map集合使用
@Mapperpublic interface SimpleMapper {@MapMapping(valueDateFormat = "dd.MM.yyyy")Map<String, String> longDateMapToStringStringMap(Map<Long, Date> source);}
5. 逆转换
// 使用注释`@InheritInverseConfiguration`表示方法应继承相应反向方法的反向配置
@Mapping(target = "age",source = "age", numberFormat = "#0.00")
PersonDTO conver(Person person);@InheritInverseConfiguration
Person conver(PersonDTO dto);