栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Springboot集成MapStruct

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Springboot集成MapStruct

MapStruct 插件是干什么的?
首先普及下VO,DO,PO,DTO的概念

​ **VO(View Object):**视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。

​ **DTO(Data Transfer Object):**数据传输对象,泛指用于展示层与服务层之间的数据传输对象。

​ **DO(Domain Object):**领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。

​ **PO(Persistent Object):**持久化对象,它跟持久层(通常是关系型数据库)的数据结构形成一一对应的映射关系,如果持久层是关系型数据库,那么,数据表中的每个字段(或若干个)就对应PO的一个(或若干个)属性。

示例解释 引用于网络中的解释
  • 用户发出请求(可能是填写表单),表单的数据在展示层被匹配为VO。

  • 展示层把VO转换为服务层对应方法所要求的DTO,传送给服务层。

  • 服务层首先根据DTO的数据构造(或重建)一个DO,调用DO的业务方法完成具体业务。一般DO的我们会省略掉,直接转PO操作数据去了

  • 服务层把DO转换为持久层对应的PO(可以使用ORM工具,也可以不用),调用持久层的持久化方法,把PO传递给它,完成持久化操作。

  • 对于一个逆向操作,如读取数据,也是用类似的方式转换和传递,略。

    不同对象之间的转换问题

  • 方案一.使用对象的get,set方法来赋值.
    手动调用get.set,对象之间属性多,类型不同的,会增加大量重复无意义的工作量,写法繁琐,没有技巧.适用于字段数量少的情况下适用

  • 方案二.使用apache的BeanUtil.copyProperties方法
    apache的BeanUtil. copyProperties,是采用对象反射来实现的,性能比较差,很多规范文件里是禁止适用,而且缺点也明显,必须转换的对象之间同属性名和类型,否则会忽略掉,这个可以自定义实现解决此问题,也不太灵活多变

  • 方案三.使用mapStruct
    基于注解实现,原理类似于lombok编译期动态生成赋值转换逻辑,方便操作,简化代码,对于包装类是自动拆箱封箱,线程安全的,性能也是可以比较强的.

如何使用 SpringBoot项目集成

maven添加依赖

    
        org.mapstruct
        mapstruct
        1.3.0.Final
    

添加插件指定编译期构建,解决项目中用lombok导致找不到类的问题

        
            org.apache.maven.plugins
            maven-compiler-plugin
            3.8.1
            
                1.8
                1.8
                UTF-8
                
                    
                        org.mapstruct
                        mapstruct-processor
                        1.3.0.Final
                    
                    
                        org.projectlombok
                        lombok
                        1.18.10
                    
                
            
        

创建接口

	@Mapper(componentModel="spring",uses = {CommonUtils.class})
	public interface OpsConverter {
	
	
	Ops opsConverter(OpsSmokeDTO dto);
	
	 * 运维单DO转 运维单VO
	 *
	 * @param ops 运维单DO
	 * @return Ops
	 */
	@Mappings({
	        @Mapping(source = "createTime",target = "createTime",qualifiedByName="dateToStr")
	})
	OpsSmokeVO opsVOConverter(Ops ops);

    
    @Mappings({
            @Mapping(source = "onTime",target = "onTime",qualifiedByName="strToDate",nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS),
            @Mapping(source = "offTime",target = "offTime",qualifiedByName="strToDate",nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS),
    })
    OpsOtherPram opsOtherPramConverter(OpsOtherPramDTO dto);

}

使用方式

// 采用了Spring管理模式可以直接@Autowired
    @Autowired
    OpsConverter opsConverter;

//方法中使用 dto为传入的前端传入的入参
	Ops ops = opsConverter.opsConverter(dto);
相关注解含义
@Mapper 只有在接口加上这个注解, MapStruct 才会去实现该接口,此@Mapper非mybatis的@Mapper

@Mapper 里有个 componentModel 属性,主要是指定实现类的类型,一般用到两个

	default:默认,可以通过 Mappers.getMapper(Class) 方式获取实例对象

	spring:在接口的实现类上自动添加注解 @Component,可通过 @Autowired 方式注入
	
    uses:表示引用的哪些类 @Mapper(componentModel="spring",uses = {DateUtils.class}),表示引用哪个类方法
        
@Mapping:属性映射,若源对象属性与目标对象名字一致,会自动映射对应属性 推荐此方式

	source:源属性 直接写源属性名 源属性中有多个嵌套对象可以使用`.`来引用,比如User对象中有个Org的名称引用,可以写user.org.name

	target:目标属性 直接写目标属性名 同源属性用法

	dateFormat:String 到 Date 日期之间相互转换,通过 SimpleDateFormat,该值为 SimpleDateFormat 的日期格式

	ignore: 忽略这个字段
	expression : 自定义表达式引入
    	比如可以调用java某个方法 expression = "java(com.derun.util.DateUtils.strToDate(source.getCreateTime()))")
    	public class DateUtils {
   		 	public static LocalDateTime strToDate(String str){
        		DateTimeFormatter df = DateTimeFormatter.ofPattern("yyy-MM-dd HH:mm:ss");
        		return LocalDateTime.parse(str,df);
    		}
		}
	qualifiedByName : 根据名称找方法,需要配合@Mapper(uses={DateUtils.class}),直接填入方法名即可,注意需要方法名上写注解@Named
            
            @Named("strToDate")
            public static LocalDateTime strToDate(String str) {
                if (StrUtil.isBlank(str)) {
                    return null;
                }
                return LocalDateTimeUtil.parse(str, "yyyy-MM-dd HH:mm:ss");
            }
@Mappings:配置多个@Mapping@MappingTarget 用于更新已有对象@InheritConfiguration 用于继承配置
// 其他的可官网上详细了解,只介绍常用的 https://mapstruct.org/
高级用法 两个类字段不一致时使用方法
@Mappings({
    @Mapping(source = "createTime",target = "createDate",qualifiedByName="dateToStr")
})
OpsSignIn opsSignInConverter(OpsSignInDTO signIn);
多对象转换
@Mappings({
        @Mapping(source = "record.samplingTime", target = "samplingTime", dateFormat = "yyyy-MM-dd HH:mm:ss"),
        @Mapping(source = "detail.openDoorTime", target = "openDoorTime", dateFormat = "yyyy-MM-dd HH:mm:ss"),
        @Mapping(source = "detail.closeDoorTime", target = "closeDoorTime", dateFormat = "yyyy-MM-dd HH:mm:ss"),
        @Mapping(source = "detail.bottleNumber",target = "bottleNumber", qualifiedByName="strToList",nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS),
        @Mapping(source = "detail.imageUrl",target = "imageUrl",  qualifiedByName="strToList",nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS),
        @Mapping(source = "record.id", target = "id")
})
SamplingRecordDetailVO detailConverter(SamplingRecord record, SamplingRecordDetail detail);
集合对象转换
List opsSysPramDTOConverter(List pramList);
编译后的代码查看

目录在target->generated-sources目录中,编译后的文件源代码

 @Override
    public SamplingRecordDetailVO detailConverter(SamplingRecord record, SamplingRecordDetail detail) {
        if ( record == null && detail == null ) {
            return null;
        }

        SamplingRecordDetailVO samplingRecordDetailVO = new SamplingRecordDetailVO();

        if ( record != null ) {
            if ( record.getSamplingTime() != null ) {
                samplingRecordDetailVO.setSamplingTime( DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss" ).format( record.getSamplingTime() ) );
            }
            samplingRecordDetailVO.setId( record.getId() );
            samplingRecordDetailVO.setOddNumber( record.getOddNumber() );
            samplingRecordDetailVO.setOrgName( record.getOrgName() );
            samplingRecordDetailVO.setOutletName( record.getOutletName() );
            samplingRecordDetailVO.setDeviceName( record.getDeviceName() );
            samplingRecordDetailVO.setOpsOrgName( record.getOpsOrgName() );
            samplingRecordDetailVO.setOpsUserName( record.getOpsUserName() );
        }
        if ( detail != null ) {
            if ( detail.getCloseDoorTime() != null ) {
                samplingRecordDetailVO.setCloseDoorTime( DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss" ).format( detail.getCloseDoorTime() ) );
            }
            if ( detail.getOpenDoorTime() != null ) {
                samplingRecordDetailVO.setOpenDoorTime( DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss" ).format( detail.getOpenDoorTime() ) );
            }
            List list = CommonUtils.strToList( detail.getImageUrl() );
            if ( list != null ) {
                samplingRecordDetailVO.setImageUrl( list );
            }
            List list1 = CommonUtils.strToList( detail.getBottleNumber() );
            if ( list1 != null ) {
                samplingRecordDetailVO.setBottleNumber( list1 );
            }
            samplingRecordDetailVO.setRemark( detail.getRemark() );
            samplingRecordDetailVO.setImageLocation( detail.getImageLocation() );
        }

        return samplingRecordDetailVO;
    }
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/631535.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号