Java 中 Convertor 是什么?一篇讲透对象转换的入门文章

很多 Java 初学者在看项目代码时,都会碰到一个词:Convertor
比如:

  • UserConvertor
  • OrderConvertor
  • BeanConvertor
  • EntityConvertor

第一次看到时,很多人会疑惑:

它到底是做什么的?为什么项目里总要写这个类?它和 DTO、VO、Entity 又是什么关系?

这篇文章就用 零基础能听懂 的方式,把 Java 里的 Convertor 讲清楚。你看完之后,基本就能明白它为什么存在、怎么写、什么时候该用。


一、先说结论:Convertor 本质上就是“对象转换器”

在 Java 项目中,Convertor 一般就是一个专门负责 把一种对象转换成另一种对象 的类。

比如:

  • 把数据库实体对象 UserEntity 转成前端展示对象 UserVO
  • 把前端传来的 UserCreateRequest 转成业务层需要的 User
  • 把一个 String 转成 IntegerDateEnum
  • 把旧系统的数据结构转成新系统的数据结构

你可以把它理解成一个“翻译官”。

不同层之间说的话不一样,Convertor 就负责翻译。


二、为什么项目里一定会有 Convertor?

很多新手会想:

“字段都一样,直接复制不就行了吗?为什么还要专门搞个 Convertor?”

原因很简单:不同层的对象职责不一样,不能混着用。

1. 数据库对象和前端对象不是一回事

举个例子,数据库里用户表可能长这样:

public class UserEntity {
    private Long id;
    private String username;
    private String password;
    private Date createTime;
}

但返回给前端时,你肯定不想把密码返回出去,所以前端展示对象可能是:

public class UserVO {
    private Long id;
    private String username;
    private String createTime;
}

这时候就需要转换:

  • password 不返回
  • createTimeDate 转成字符串格式

这就是 Convertor 的工作。

2. 避免不同层“直接耦合”

一个规范的 Java 项目,通常会分层:

  • Controller 层:接收请求、返回响应
  • Service 层:处理业务逻辑
  • Repository/Mapper 层:访问数据库

不同层往往使用不同对象:

  • RequestDTO:前端传来的请求对象
  • Entity/DO/PO:数据库实体对象
  • VO:返回给前端的展示对象
  • BO:业务对象

如果所有层都共用同一个对象,会导致:

  • 字段越来越乱
  • 安全风险变大
  • 修改一处影响全局
  • 维护成本非常高

所以需要一个独立的“转换层”,这就是 Convertor


三、Java 项目中常见的 Convertor 使用场景

1. DTO -> Entity

前端提交注册请求:

public class UserRegisterDTO {
    private String username;
    private String password;
}

数据库实体:

public class UserEntity {
    private Long id;
    private String username;
    private String password;
    private Date createTime;
}

转换逻辑:

public class UserConvertor {

    public static UserEntity dtoToEntity(UserRegisterDTO dto) {
        UserEntity entity = new UserEntity();
        entity.setUsername(dto.getUsername());
        entity.setPassword(dto.getPassword());
        entity.setCreateTime(new Date());
        return entity;
    }
}

2. Entity -> VO

数据库查出来的是 UserEntity,前端需要的是 UserVO

public class UserConvertor {

    public static UserVO entityToVO(UserEntity entity) {
        UserVO vo = new UserVO();
        vo.setId(entity.getId());
        vo.setUsername(entity.getUsername());
        vo.setCreateTime(
            new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(entity.getCreateTime())
        );
        return vo;
    }
}

3. List 集合转换

很多时候不是转一个对象,而是转一批:

public static List<UserVO> entityListToVOList(List<UserEntity> entityList) {
    List<UserVO> voList = new ArrayList<>();
    for (UserEntity entity : entityList) {
        voList.add(entityToVO(entity));
    }
    return voList;
}

四、为什么不用同一个对象一路传到底?

这是初学者最容易问的问题。

比如为什么不直接让前端提交 UserEntity,数据库也存 UserEntity,返回给前端还是 UserEntity

答案是:短期省事,长期灾难。

如果全都用一个对象,会出现什么问题?

1. 安全问题

比如 passworddeletedisAdmin 这种字段,不应该直接暴露给前端。

2. 职责混乱

数据库对象是为了存储数据,前端对象是为了展示页面,这本来就是两个用途。

3. 扩展困难

今天数据库里有 createTimeDate 类型,前端要字符串;明天前端又想加个“用户等级描述”,这个字段数据库里根本没有。
如果没有转换层,代码会越来越难维护。

所以说:

Convertor 的本质价值,不是“复制字段”,而是“隔离层次、控制边界”。


五、Convertor 和 Converter 有什么区别?

这里要特别解释一下。

1. 从英语上说,标准写法更推荐 Converter

在英文里,更常见、也更标准的写法是:

  • Converter

而不是:

  • Convertor

2. 但很多 Java 项目里确实写 Convertor

尤其是一些老项目、公司内部项目、脚手架代码里,经常会看到:

  • UserConvertor
  • OrderConvertor

这其实是一种 项目命名习惯,不是 Java 官方语法。

3. 实际开发里怎么理解?

你只需要记住:

  • ConvertorConverter 在很多项目里说的是同一个东西
  • 都表示“转换器”
  • 只是命名风格不同

如果是你自己新写项目,通常更推荐统一用 Converter,因为更符合英文习惯和 Spring 的官方接口命名。


六、Java 中最常见的 Convertor 写法


写法一:手写工具类

这是最常见、最适合初学者理解的方式。

public class UserConvertor {

    public static UserVO entityToVO(UserEntity entity) {
        if (entity == null) {
            return null;
        }

        UserVO vo = new UserVO();
        vo.setId(entity.getId());
        vo.setUsername(entity.getUsername());
        vo.setCreateTime(
            new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(entity.getCreateTime())
        );
        return vo;
    }
}

优点

  • 简单直接
  • 容易理解
  • 适合小项目

缺点

  • 字段多时很繁琐
  • 容易重复写大量模板代码

写法二:使用 Spring 的 Converter<S, T> 接口

Spring 框架里本身就有一个官方接口:

org.springframework.core.convert.converter.Converter

定义如下:

public interface Converter<S, T> {
    T convert(S source);
}

你可以自己实现它:

import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

@Component
public class StringToIntegerConverter implements Converter<String, Integer> {

    @Override
    public Integer convert(String source) {
        return Integer.valueOf(source);
    }
}

这种方式适合什么?

适合 类型转换,比如:

  • String -> Integer
  • String -> LocalDate
  • String -> Enum

尤其是在 Spring MVC 参数绑定、配置绑定时很常见。

注意

Spring 的 Converter 更偏向 框架级类型转换
而业务项目里说的 UserConvertorOrderConvertor,更多是 对象之间的业务转换


写法三:使用 MapStruct 自动生成转换代码

如果项目里对象很多,字段很多,手写会很痛苦,这时通常会用 MapStruct

示例:

@Mapper(componentModel = "spring")
public interface UserConverter {

    UserVO entityToVO(UserEntity entity);

    UserEntity dtoToEntity(UserRegisterDTO dto);
}

MapStruct 会在编译期自动帮你生成实现类。

优点

  • 代码简洁
  • 性能好
  • 比反射工具更安全
  • 非常适合中大型项目

缺点

  • 初学者要先学配置
  • 字段复杂时仍然需要自定义映射

七、一个完整案例:从请求对象到返回对象

下面用一个完整链路来帮助理解。

1. 前端传入注册请求

public class UserRegisterDTO {
    private String username;
    private String password;
}

2. 数据库存储对象

public class UserEntity {
    private Long id;
    private String username;
    private String password;
    private Date createTime;
}

3. 返回给前端的对象

public class UserVO {
    private Long id;
    private String username;
    private String createTime;
}

4. Convertor 代码

public class UserConvertor {

    public static UserEntity dtoToEntity(UserRegisterDTO dto) {
        if (dto == null) {
            return null;
        }

        UserEntity entity = new UserEntity();
        entity.setUsername(dto.getUsername());
        entity.setPassword(dto.getPassword());
        entity.setCreateTime(new Date());
        return entity;
    }

    public static UserVO entityToVO(UserEntity entity) {
        if (entity == null) {
            return null;
        }

        UserVO vo = new UserVO();
        vo.setId(entity.getId());
        vo.setUsername(entity.getUsername());

        if (entity.getCreateTime() != null) {
            vo.setCreateTime(
                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(entity.getCreateTime())
            );
        }

        return vo;
    }
}

5. Controller / Service 中使用

@PostMapping("/register")
public UserVO register(@RequestBody UserRegisterDTO dto) {
    UserEntity entity = UserConvertor.dtoToEntity(dto);
    userService.save(entity);
    return UserConvertor.entityToVO(entity);
}

这就是最典型的 Java 项目对象转换流程。


八、初学者必须理解的几个概念

1. DTO 是什么?

DTO 全称 Data Transfer Object,数据传输对象。
一般用于接收前端参数,或者系统之间传输数据。

可以理解成:

“别人传给你的数据包装盒”


2. Entity / DO / PO 是什么?

这些一般和数据库相关:

  • Entity:实体类
  • DO:Data Object
  • PO:Persistent Object

不同公司叫法不同,但本质差不多。
你可以理解成:

“数据库那边的数据结构”


3. VO 是什么?

VO 常见含义是 View Object,视图对象。
它通常是返回给前端展示的对象。

你可以理解成:

“页面上真正需要展示的数据结构”


4. Convertor 的作用是什么?

一句话概括:

在 DTO、Entity、VO 这些不同对象之间做转换。


九、项目里什么时候应该写 Convertor?

下面这几种情况,非常适合写:

1. 前后端字段不完全一致

比如数据库里叫 createTime,前端想要 create_time 或格式化字符串。

2. 需要隐藏敏感字段

比如密码、权限字段、删除标记。

3. 一个对象要拆成多个对象使用

比如数据库对象很大,但前端只需要其中几个字段。

4. 多层架构需要解耦

Controller、Service、Repository 各用各的对象,职责更清晰。


十、什么时候不需要单独写 Convertor?

也不是所有项目都要写得特别复杂。

1. 特别小的练手项目

如果只有几个类,字段也很少,可以先手写,不一定非得单独抽类。

2. 两个对象完全一致,而且只用一次

这种情况下,临时转一下也可以。

但只要项目一旦变大,Convertor 几乎都会变成刚需


十一、Convertor 里该不该写业务逻辑?

原则上不应该。

Convertor 最核心的职责是:

  • 字段映射
  • 数据格式转换
  • 简单组装

它不适合做这些事:

  • 查数据库
  • 调远程接口
  • 写复杂判断
  • 写核心业务规则

错误示例:

public class UserConvertor {
    public static UserVO entityToVO(UserEntity entity) {
        UserVO vo = new UserVO();
        vo.setId(entity.getId());
        vo.setUsername(entity.getUsername());

        // 不推荐:这里面做复杂业务
        if (entity.getScore() > 1000) {
            vo.setLevelName("高级用户");
        } else {
            vo.setLevelName("普通用户");
        }

        return vo;
    }
}

如果只是简单展示还勉强能接受,但复杂业务逻辑应该放在 Service 层。

记住一句话:

Convertor 负责“转换”,Service 负责“业务”。


十二、Java 初学者常见误区

误区 1:Convertor 就是复制粘贴字段

不完全对。
它不仅是复制字段,还包括:

  • 类型转换
  • 格式处理
  • 过滤字段
  • 解耦层次

误区 2:字段一样就没必要写 Convertor

短期看似省代码,长期会让层与层之间耦合严重。

误区 3:Convertor 和 Spring Converter 是一回事

不是完全一样。

  • UserConvertor:项目里的对象转换器
  • Converter<S, T>:Spring 提供的类型转换接口

两者思想相通,但使用场景不同。

误区 4:Convertor 一定是官方语法

不是。
它通常只是项目里的一个普通类名或命名约定。


十三、实际开发中更推荐哪种方案?

小项目、学习阶段

推荐先手写 Convertor

原因:

  • 容易理解
  • 能看清字段映射过程
  • 有助于理解分层思想

中大型项目

推荐:

  • 统一命名规范
  • 优先使用 Converter
  • 对大量对象转换使用 MapStruct

这样更规范,也更省代码。


十四、建议的命名方式

如果你是自己写项目,建议这样命名:

  • UserConverter
  • OrderConverter
  • ProductConverter

如果你接手的是老项目,已经统一写成 Convertor,那就保持一致,不要一半 Convertor 一半 Converter

最重要的不是拼写,而是统一。

团队里命名一旦不统一,维护成本会明显上升。


十五、面试时怎么回答“什么是 Convertor”?

如果面试官问你,你可以这样回答:

在 Java 项目里,Convertor 通常指对象转换器,用来在 DTO、Entity、VO 等不同对象之间做数据转换。
它的主要作用是解耦不同层的数据结构,避免直接暴露数据库对象,同时方便做字段过滤、类型转换和格式处理。
小项目可以手写,大项目通常会结合 MapStruct 之类的工具来做自动转换。

这段回答已经比较完整了。


十六、总结:一句话彻底记住 Convertor

你可以把 Convertor 理解成 Java 项目中的“翻译层”。

它解决的是:

  • 不同对象之间如何转换
  • 不同层之间如何解耦
  • 数据如何安全、规范地流转

所以它的本质不是“多写一个类”,而是:

让系统结构更清晰,让数据边界更明确,让代码更容易维护。


十七、本文核心要点回顾

  • Convertor 本质上是“对象转换器”
  • 常见用于 DTOEntityVO 之间的转换
  • 它存在的核心原因是“解耦”和“控制数据边界”
  • ConvertorConverter 大多是同类概念,后者更标准
  • Spring 的 Converter<S,T> 更偏框架类型转换
  • 小项目可以手写,大项目建议用 MapStruct
  • Convertor 里不要堆复杂业务逻辑
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐