父类:ContCustomerVO,原来业务类:ContNewCustomer extends ContCustomer
核心原则:数据库 Entity、业务 Controller 类继承 ≠ VO 就一定要继承,VO 是面向接口输出 / 入参,要结合场景选。
方案 1:VO 继承(ContNewCustomerVO extends ContCustomerVO)
✅优点
- 公共字段只写一份,减少重复代码;父类改字段,子类自动生效
- 和后端 Model 继承结构对齐,代码直观
- 序列化(Jackson)正常工作,父类 get/set、注解
@ApiModelProperty、校验注解@NotBlank子类全部继承生效
❌缺点
- 字段无法隐藏:如果新客户接口不需要父类中某几个字段,继承会全部带出来,不能直接删掉,只能用
@JsonIgnore排除,多了一堆忽略注解 - 前端文档 (Swagger) 会把父类所有字段全部展示出来,容易混淆;
- 如果父类后续新增字段,子类 VO 会被动带上,容易出现无意泄露字段;
- 嵌套层级,调试看 JSON 结构会多一层继承关系。
适合场景:新客户 VO 只是在原有客户基础上新增少量字段,不需要剔除父类任何字段。
@Data
public class ContCustomerVO {
private Long id;
private String customerName;
private String phone;
}
@Data
public class ContNewCustomerVO extends ContCustomerVO {
// 只写新增的字段
private String inviteCode;
private LocalDateTime registerTime;
}
方案 2:全字段拷贝(不继承,复制所有字段)
✅优点
- 完全自主控制输出字段,不需要的字段直接不写,接口返回干净;
- 不受父类改动影响,父类加字段,本 VO 不会被动增加;接口稳定性高;
- Swagger 文档干净,没有继承带来的一堆无关字段;
- 不会出现莫名其妙
@JsonIgnore一堆字段。
❌缺点
- 大量重复字段;父类修改字段,子类 VO 要同步改,容易漏改;
- 和业务类继承结构不一致,阅读代码会疑惑。
适合场景:新客户接口和普通客户接口字段差异大,需要丢弃部分父类字段。
🔥工程上最佳实践(我们业务系统常用)
- Entity 可以大胆继承(数据库映射,复用公共数据库字段)
- VO 优先看接口输出:
- 如果接口输出几乎全部父类字段,只加几个:用继承 VO
- 如果接口要丢弃一部分父类字段:不要继承,手写全部需要的字段
坑提醒:很多人直接照搬业务类继承给 VO,后续父类加敏感字段,VO 直接返回给前端,造成数据泄露。
折中方案(不想复制字段,又要过滤输出)
继承 VO + DTO 转换层,不要直接把数据库对应的 VO 返回前端。 ContNewCustomer(entity) → 转成前端输出DTO,转换的时候显式指定需要哪些字段。
快速判断一句话
ContNewCustomer 是业务逻辑继承;VO 是接口契约。 接口返回字段 = 父类全部字段 + 少量新增 → 继承 VO 接口返回字段 ≠ 父类全部字段(要删部分字段) → 直接写全字段,不要继承
举个例子
普通客户 VO:id,name,phone,balance,deleteFlag 新客户接口:只需要 id,name,phone,不需要 balance、deleteFlag 👉 不要继承,直接手写需要字段,不要继承然后 @JsonIgnore balance、deleteFlag。

829

被折叠的 条评论
为什么被折叠?



