最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中DTO和VO的區(qū)別舉例詳解

 更新時間:2025年12月25日 10:53:33   作者:趁你還年輕_  
在Java開發(fā)中,VO和DTO都是用于數據傳輸的對象,但它們的含義和用途有所不同,這篇文章主要介紹了Java中DTO和VO區(qū)別的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

前言

DTO(Data Transfer Object)和 VO(Value Object / View Object)是 Java 開發(fā)中用于不同層次間數據傳遞的對象,但它們的設計目的和使用場景有本質區(qū)別。

一、概念定義

DTO(Data Transfer Object)

  • 定義:用于在不同層或系統(tǒng)之間傳輸數據的對象

  • 核心作用:減少遠程調用次數,打包多個數據一次性傳輸

  • 典型場景:Service 層返回數據給 Controller 層、微服務間調用

VO(Value Object / View Object)

  • 定義:用于前端展示的數據對象,封裝頁面需要的數據

  • 核心作用:適配前端展示需求,隱藏后端敏感字段

  • 典型場景:Controller 層返回給前端

二、核心區(qū)別對比表

對比維度DTO (Data Transfer Object)VO (View Object)
設計目的減少網絡調用,批量傳輸數據適配前端展示需求
數據范圍可能包含多個聚合的數據針對單個頁面/組件定制
數據敏感度可包含內部字段必須隱藏敏感字段(密碼、金額等)
使用層次Service ↔ Controller、微服務間調用Controller ↔ 前端
字段格式化通常是原始數據類型包含格式化后的數據(如日期、金額顯示格式)
變更頻率相對穩(wěn)定隨前端需求頻繁變化

三、詳細說明與代碼示例

場景:用戶訂單詳情查詢

數據庫實體(DO - Data Object)

@Entity
@Table(name = "t_user")
public class UserDO {
    private Long id;
    private String username;
    private String password; // 敏感字段
    private String email;
    private String phone;
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
    private Integer status; // 0-注銷 1-正常 2-凍結
}

DTO(Service 層返回)

@Data
public class UserOrderDTO {
    // 用戶基本信息
    private Long userId;
    private String username;
    private String email; // 可能包含敏感信息
    
    // 訂單列表(跨聚合數據)
    private List<OrderDTO> orders;
    
    // 統(tǒng)計信息
    private Integer totalOrderCount;
    private BigDecimal totalAmount;
    
    // 原始數據類型
    private LocalDateTime userCreateTime;
}

使用場景:Service 層查詢用戶和訂單數據,打包返回給 Controller

@Service
public class UserOrderService {
    public UserOrderDTO getUserWithOrders(Long userId) {
        UserDO user = userDao.findById(userId);
        List<OrderDO> orders = orderDao.findByUserId(userId);
        
        // 轉換并聚合數據
        UserOrderDTO dto = new UserOrderDTO();
        dto.setUserId(user.getId());
        dto.setUsername(user.getUsername());
        dto.setEmail(user.getEmail()); // 直接暴露原始郵箱
        dto.setOrders(convertOrders(orders));
        dto.setTotalOrderCount(orders.size());
        return dto;
    }
}

VO(Controller 層返回前端)

@Data
public class UserOrderVO {
    // 前端展示字段(脫敏)
    private Long userId;
    private String username;
    private String maskedEmail; // 脫敏:a****@gmail.com
    
    // 訂單數據(按需展示)
    private List<OrderVO> orders;
    
    // 格式化后的數據
    private String formattedTotalAmount; // "¥9,999.00"
    private String userCreateTimeDesc; // "2025-01-15 12:00"
    
    // 前端狀態(tài)(計算得出)
    private String userStatusText; // "正常" 而非 1
    
    // 不包含:password, phone, raw status
}

使用場景:Controller 層轉換 DTO 為 VO,適配前端展示

@RestController
@RequestMapping("/api/users")
public class UserOrderController {
    
    @Resource
    private UserOrderService userOrderService;
    
    @GetMapping("/{userId}/orders")
    public ResultVO<UserOrderVO> getUserOrders(@PathVariable Long userId) {
        UserOrderDTO dto = userOrderService.getUserWithOrders(userId);
        
        // DTO → VO 轉換(關鍵一步!)
        UserOrderVO vo = new UserOrderVO();
        vo.setUserId(dto.getUserId());
        vo.setUsername(dto.getUsername());
        
        // 1. 脫敏處理
        vo.setMaskedEmail(maskEmail(dto.getEmail())); // a****@gmail.com
        
        // 2. 數據格式化
        vo.setFormattedTotalAmount(formatCurrency(dto.getTotalAmount()));
        vo.setUserCreateTimeDesc(formatDateTime(dto.getUserCreateTime()));
        
        // 3. 狀態(tài)轉換
        vo.setUserStatusText(convertStatusToText(user.getStatus())); // "正常"
        
        // 4. 按需過濾字段
        vo.setOrders(convertToOrderVO(dto.getOrders()));
        
        return ResultVO.success(vo);
    }
}

四、常見誤區(qū)與反例

? 誤區(qū) 1:DTO 和 VO 混用

// 錯誤:Controller 直接返回 DTO,暴露敏感信息
@RestController
public class UserController {
    public UserOrderDTO getUserOrders(Long userId) {
        return userOrderService.getUserWithOrders(userId); // ? 暴露了 password 等字段
    }
}

? 誤區(qū) 2:VO 包含業(yè)務邏輯

// 錯誤:VO 包含計算邏輯
@Data
public class UserOrderVO {
    private BigDecimal orderAmount;
    private BigDecimal discount;
    
    // ? VO 只應承載數據,不應有業(yè)務方法
    public BigDecimal getPayAmount() {
        return orderAmount.subtract(discount); // 計算應在后端完成
    }
}

? 誤區(qū) 3:過度使用 DTO 導致類爆炸

// 錯誤:為每個方法都創(chuàng)建 DTO
public class UserOrderService {
    public UserOrderDTO1 method1() { ... }
    public UserOrderDTO2 method2() { ... }
    public UserOrderDTO3 method3() { ... } // 維護噩夢
}

? 正確做法:合理復用 DTO,僅在字段差異大時創(chuàng)建新類

五、與其他對象的關系

在分層架構中,完整的對象體系如下:

完整對象體系

縮寫全稱作用位置示例
DOData Object持久層 ↔ 數據庫UserDO(對應數據庫表)
DTOData Transfer ObjectService ↔ ControllerUserOrderDTO(聚合數據)
VOView ObjectController ↔ 前端UserOrderVO(脫敏+格式化)
BOBusiness ObjectService 層內部OrderBO(處理業(yè)務邏輯)
POPersistant Object同 DO(老叫法)UserPO
AOApplication Object應用層參數LoginAO(登錄參數)

六、最佳實踐總結

1. 轉換時機明確

// 分層轉換
DAO層 → Service層 → Controller層 → 前端
  DO   →   DTO    →    VO      → JSON

2. 命名規(guī)范

// DTO 命名:業(yè)務 + DTO
UserDTO, OrderDTO, UserOrderDTO
 
// VO 命名:頁面/組件 + VO
OrderListVO, OrderDetailVO, UserProfileVO

3. 工具類輔助轉換

@Component
public class UserConverter {
    
    // DO → DTO
    public UserDTO toDTO(UserDO userDO) {
        UserDTO dto = new UserDTO();
        BeanUtils.copyProperties(userDO, dto);
        return dto;
    }
    
    // DTO → VO(關鍵:脫敏+格式化)
    public UserVO toVO(UserDTO userDTO) {
        UserVO vo = new UserVO();
        vo.setUserId(userDTO.getUserId());
        vo.setUsername(userDTO.getUsername());
        vo.setMaskedEmail(this.maskEmail(userDTO.getEmail()));
        vo.setStatusText(this.convertStatus(userDTO.getStatus()));
        return vo;
    }
    
    private String maskEmail(String email) {
        // 脫敏邏輯
        return email.replaceAll("(?<=.).(?=.*@)", "*");
    }
}

4. 統(tǒng)一返回結構

@Data
public class ResultVO<T> {
    private int code;      // 狀態(tài)碼
    private String message; // 提示信息
    private T data;        // 實際數據(VO/DTO)
    
    public static <T> ResultVO<T> success(T data) {
        ResultVO<T> result = new ResultVO<>();
        result.setCode(200);
        result.setMessage("success");
        result.setData(data);
        return result;
    }
}

七、總結

規(guī)則DTOVO
核心目標傳輸效率(減少調用次數)展示安全(適配前端+脫敏)
數據來源可能跨多個聚合通?;趩蝹€ DTO
是否脫敏? 否必須脫敏
是否格式化? 原始數據前端友好格式
位置Service → ControllerController → 前端

設計原則先設計 VO 滿足前端需求,再反推 DTO 需要聚合哪些數據,最后確定 DO 的數據庫設計。

一句話總結DTO 為服務層效率而生,VO 為前端安全而生。

到此這篇關于Java中DTO和VO區(qū)別的文章就介紹到這了,更多相關Java DTO和VO區(qū)別內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 一文詳解如何在idea中快速搭建一個Spring?Boot項目

    一文詳解如何在idea中快速搭建一個Spring?Boot項目

    IntelliJ IDEA作為Java開發(fā)者的?首選IDE?,深度集成Spring Boot支持,可一鍵生成項目骨架、智能配置依賴,這篇文章主要介紹了如何在idea中快速搭建一個Spring?Boot項目的相關資料,需要的朋友可以參考下
    2025-06-06
  • Spring AOP定義Before增加實戰(zhàn)案例詳解

    Spring AOP定義Before增加實戰(zhàn)案例詳解

    這篇文章主要介紹了Spring AOP定義Before增加,結合實例形式詳細分析了Spring面向切面AOP定義Before增加相關定義與使用技巧,需要的朋友可以參考下
    2020-01-01
  • skywalking分布式服務調用鏈路追蹤APM應用監(jiān)控

    skywalking分布式服務調用鏈路追蹤APM應用監(jiān)控

    這篇文章主要為大家介紹了skywalking分布式服務調用鏈路追蹤APM應用監(jiān)控的功能使用說明,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-03-03
  • 一文了解Spring中攔截器的原理與使用

    一文了解Spring中攔截器的原理與使用

    在web開發(fā)中,攔截器是經常用到的功能。它可以幫我們預先設置數據以及統(tǒng)計方法的執(zhí)行效率等等。今天就來詳細的談一下spring中的攔截器,需要的可以參考一下
    2022-06-06
  • Spring Cloud Ribbon的踩坑記錄與原理詳析

    Spring Cloud Ribbon的踩坑記錄與原理詳析

    這篇文章主要給大家介紹了關于Spring Cloud Ribbon踩坑記錄與原理的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-10-10
  • SpringCloud?Alibaba環(huán)境集成之nacos詳解

    SpringCloud?Alibaba環(huán)境集成之nacos詳解

    Spring?Cloud?Alibaba提供了越來越完善的各類微服務治理組件,比如分布式服務配置與注冊中心nacos,服務限流、熔斷組件sentinel等,本篇先來介紹SpringCloud?Alibaba環(huán)境集成之nacos詳解,需要的朋友可以參考下
    2023-03-03
  • Java實現在Word指定位置插入分頁符

    Java實現在Word指定位置插入分頁符

    在Word插入分頁符可以在指定段落后插入,也可以在特定文本位置處插入。本文將以Java代碼來操作以上兩種文檔分頁需求,需要的可以參考一下
    2022-04-04
  • 詳解什么是Java線程池的拒絕策略?

    詳解什么是Java線程池的拒絕策略?

    今天給大家總結一下線程池的拒絕策略,文中有非常詳細的介紹及代碼示例,對正在學習java的小伙伴們有很好地幫助,需要的朋友可以參考下
    2021-05-05
  • 利用Java實現玩家打怪小游戲的完整過程

    利用Java實現玩家打怪小游戲的完整過程

    這篇文章主要介紹了如何使用Java創(chuàng)建一個簡單的“打怪小游戲”,游戲中的角色分為法師、戰(zhàn)士、BOSS和一個Team類,代碼展示了如何通過面向對象編程來實現一個基本的戰(zhàn)斗系統(tǒng),需要的朋友可以參考下
    2024-12-12
  • Mybatis框架中Interceptor接口的使用說明

    Mybatis框架中Interceptor接口的使用說明

    這篇文章主要介紹了Mybatis框架中Interceptor接口的使用說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09

最新評論

杭锦后旗| 临夏县| 德格县| 汉川市| 万年县| 鄂州市| 杭锦旗| 古丈县| 军事| 大渡口区| 江口县| 蓬溪县| 潼南县| 景宁| 京山县| 萨迦县| 禄劝| 河北区| 芮城县| 古蔺县| 南昌市| 大石桥市| 藁城市| 德令哈市| 基隆市| 大埔县| 山东省| 韩城市| 平潭县| 新疆| 嘉峪关市| 赤水市| 新民市| 曲水县| 榕江县| 图木舒克市| 博野县| 乌苏市| 象山县| 华阴市| 古浪县|