《Java 中 Convertor 是什么?从 0 到 1 讲透对象转换器的作用、写法和使用场景》
Java 中 Convertor 是什么?一篇讲透对象转换的入门文章
很多 Java 初学者在看项目代码时,都会碰到一个词:Convertor。
比如:
UserConvertorOrderConvertorBeanConvertorEntityConvertor
第一次看到时,很多人会疑惑:
它到底是做什么的?为什么项目里总要写这个类?它和 DTO、VO、Entity 又是什么关系?
这篇文章就用 零基础能听懂 的方式,把 Java 里的 Convertor 讲清楚。你看完之后,基本就能明白它为什么存在、怎么写、什么时候该用。
一、先说结论:Convertor 本质上就是“对象转换器”
在 Java 项目中,Convertor 一般就是一个专门负责 把一种对象转换成另一种对象 的类。
比如:
- 把数据库实体对象
UserEntity转成前端展示对象UserVO - 把前端传来的
UserCreateRequest转成业务层需要的User - 把一个
String转成Integer、Date、Enum - 把旧系统的数据结构转成新系统的数据结构
你可以把它理解成一个“翻译官”。
不同层之间说的话不一样,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不返回createTime从Date转成字符串格式
这就是 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. 安全问题
比如 password、deleted、isAdmin 这种字段,不应该直接暴露给前端。
2. 职责混乱
数据库对象是为了存储数据,前端对象是为了展示页面,这本来就是两个用途。
3. 扩展困难
今天数据库里有 createTime 是 Date 类型,前端要字符串;明天前端又想加个“用户等级描述”,这个字段数据库里根本没有。
如果没有转换层,代码会越来越难维护。
所以说:
Convertor 的本质价值,不是“复制字段”,而是“隔离层次、控制边界”。
五、Convertor 和 Converter 有什么区别?
这里要特别解释一下。
1. 从英语上说,标准写法更推荐 Converter
在英文里,更常见、也更标准的写法是:
Converter
而不是:
Convertor
2. 但很多 Java 项目里确实写 Convertor
尤其是一些老项目、公司内部项目、脚手架代码里,经常会看到:
UserConvertorOrderConvertor
这其实是一种 项目命名习惯,不是 Java 官方语法。
3. 实际开发里怎么理解?
你只需要记住:
Convertor和Converter在很多项目里说的是同一个东西- 都表示“转换器”
- 只是命名风格不同
如果是你自己新写项目,通常更推荐统一用 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 -> IntegerString -> LocalDateString -> Enum
尤其是在 Spring MVC 参数绑定、配置绑定时很常见。
注意
Spring 的 Converter 更偏向 框架级类型转换,
而业务项目里说的 UserConvertor、OrderConvertor,更多是 对象之间的业务转换。
写法三:使用 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 ObjectPO: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
这样更规范,也更省代码。
十四、建议的命名方式
如果你是自己写项目,建议这样命名:
UserConverterOrderConverterProductConverter
如果你接手的是老项目,已经统一写成 Convertor,那就保持一致,不要一半 Convertor 一半 Converter。
最重要的不是拼写,而是统一。
团队里命名一旦不统一,维护成本会明显上升。
十五、面试时怎么回答“什么是 Convertor”?
如果面试官问你,你可以这样回答:
在 Java 项目里,Convertor 通常指对象转换器,用来在 DTO、Entity、VO 等不同对象之间做数据转换。
它的主要作用是解耦不同层的数据结构,避免直接暴露数据库对象,同时方便做字段过滤、类型转换和格式处理。
小项目可以手写,大项目通常会结合 MapStruct 之类的工具来做自动转换。
这段回答已经比较完整了。
十六、总结:一句话彻底记住 Convertor
你可以把 Convertor 理解成 Java 项目中的“翻译层”。
它解决的是:
- 不同对象之间如何转换
- 不同层之间如何解耦
- 数据如何安全、规范地流转
所以它的本质不是“多写一个类”,而是:
让系统结构更清晰,让数据边界更明确,让代码更容易维护。
十七、本文核心要点回顾
Convertor本质上是“对象转换器”- 常见用于
DTO、Entity、VO之间的转换 - 它存在的核心原因是“解耦”和“控制数据边界”
Convertor和Converter大多是同类概念,后者更标准- Spring 的
Converter<S,T>更偏框架类型转换 - 小项目可以手写,大项目建议用
MapStruct Convertor里不要堆复杂业务逻辑
更多推荐




所有评论(0)