2021-11-07

VO(视图模型) 与 DTO(数据传输对象)


前言

VO(View Object):VO是显示视图模型,视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。举例:展示层将DTO传送过来男性显示成帅哥(客户端1),或者显示成靓仔(客户端2);将帅哥或者靓仔,转换成男性,以DTO形式请求服务端。

DTO(Data Transfer Object):DTO是传输模型,数据传输对象,在这里泛指用于展示层与服务层之间的数据传输对象。如果是一个DTO对应一个VO,则DTO=VO;但是如果一个DTO对应多个VO,则展示层需要把VO转换为服务层对应方法所要求的DTO,传送给服务层。从而达到服务层与展示层解耦的效果。数据传输目标往往是数据访问对象从数据库中检索数据。假设你数据库中定义了User类,包含用户名、密码、邮箱、手机号等等;当用户登录时一般只需要输入用户名和密码,那么传入服务端的用户名和密码就可以在controller层封装到UserDTO实体类中。


一、DTO

一个DTO可以对应多个从仓储层返回的DO(Domain Object,领域模型)的json数组,这里可以使用AutoMapper来进行自适配。DTO不是为MVC的视图而存在的模型,而是为了适应来自前端请求而存在的。DTO模型把来自前端的请求(这个请求不管来自前后端分离的页面,还是mvc的视图页面)封装在DTO模型中,然后服务端处理转换成Entity Framework中的领域模型。

在一个DTO对应一个VO的时候,DTO = 视图模型。 DTO 和 VO 的属性值基本是一致的,而且他们通常都是 json对象,因此没必要多此一举,但不要忘记这是实现层面的思维,对于设计层面来说,概念上还是应该存在 VO 和 DTO ,因为两者有着本质的区别,DTO 代表服务层需要接收的数据和返回的数据,而 VO 代表展示层需要显示的数据。应用时,可以在前端将DTO包成VO,也可以在服务端的Controller层,service层包成VO。VO转换成DTO同理。在这种情况下可以实现,前后端相关的东西只有api的url和vo,而且大多数情况也是只有一个客户端的。

在一个DTO对应多个VO的时候,DTO ≠ 视图模型。此时需要在前端将男性打包成帅哥或者靓仔显示;请求数据时,也需要前端将帅哥或者靓仔转换成男性,以DTO形式请求服务端。

在这里插入图片描述

  • 用户发出请求(可能是填写表单),表单的数据在展示层被匹配为VO。
  • 展示层把VO转换为服务层对应方法所要求的DTO,传送给服务层。
  • 服务层首先根据DTO的数据构造(或重建)一个DO,调用DO的业务方法完成具体业务。
  • 服务层把DO转换为持久层对应的PO(可以使用ORM工具,也可以不用),调用持久层的持久化方法,把PO传递给它,完成持久化操作。

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

二、MapStruct

<!--mapStruct相关依赖-->
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-jdk8</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>
    <!--mapStruct相关依赖-->
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-processor</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>

使用MapStruct需要编写convert接口

 
import com.pbteach.java.mapstruct.model.UserDetailVo;
import com.pbteach.java.mapstruct.model.UserDto;
import com.pbteach.java.mapstruct.model.UserVo;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
 
 
@Mapper//接口上加此注解mapstruct自动实现该接口
public interface UserConvert {
    UserConvert INSTANCE = Mappers.getMapper(UserConvert.class);
 
    /**
     * 一个对象映射为一个对象
     @Mapping:属性映射,当源对象属性与目标对象属性名一致时无需定义,否则需要定义映射对应的属性
     source:源属性
     target:目标属性
     */
    @Mappings({
            @Mapping(source = "fullname", target = "name")
    })
    UserDto vo2dto(UserVo vo);
 
    //两个对象映射为一个对象
    @Mappings({
            @Mapping(source = "vo.fullname", target = "name")
    })
    UserDto vo2dto(UserVo vo, UserDetailVo userDetailVo);
 
    //dto转成vo
    @Mappings({
        @Mapping(source = "name", target = "fullname")
    })
    UserVo dto2vo(UserDto dto);
 
}

将vo转为dto

UserDto userDto = UserConvert.INSTANCE.vo2dto(userVo);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值