文章目录
前言
微服务下 DTO 设计核心原则:
对外稳定,对内隔离,禁止直接复用数据库对象。
一、微服务调用链
text
order-service
↓ Feign / RPC
user-service
stock-service
coupon-service
pay-service
服务之间传的对象一般就是:
text
RequestDTO / ResponseDTO
二、推荐命名
请求对象
java
CreateOrderRequest
DeductStockRequest
UserQueryRequest
或者:
java
CreateOrderDTO
DeductStockDTO
我更推荐微服务接口用:
text
XXXRequest / XXXResponse
因为语义更清楚。
三、Feign 接口示例
stock-api 模块
java
@FeignClient(name = "stock-service")
public interface StockClient {
@PostMapping("/api/stock/deduct")
StockDeductResponse deduct(@RequestBody StockDeductRequest request);
}
请求 DTO
java
public class StockDeductRequest {
private Long skuId;
private Integer count;
private String requestId;
}
返回 DTO
java
public class StockDeductResponse {
private Boolean success;
private String code;
private String message;
}
四、微服务 DTO 不要放在哪?
不要放在:
text
order-service 内部 domain 包
stock-service 内部 entity 包
否则其他服务依赖会很乱。
推荐建独立 API 包:
text
stock-api
├── client
│ └── StockClient.java
├── dto
│ ├── StockDeductRequest.java
│ └── StockDeductResponse.java
然后:
text
order-service 依赖 stock-api
stock-service 实现 stock-api
五、不要直接暴露 Entity / DO
错误示例:
java
@PostMapping("/user/get")
UserDO getUser(@RequestBody UserDO user);
问题:
text
数据库结构泄露
字段一改,调用方全炸
可能暴露敏感字段
服务边界不清晰
正确:
java
UserQueryRequest
UserResponse
六、DTO 要分"入参"和"出参"
不要一个对象到处复用。
错误:
java
UserDTO 同时用于创建、修改、查询、返回
正确:
java
UserCreateRequest
UserUpdateRequest
UserQueryRequest
UserResponse
因为不同场景字段不一样:
text
创建需要 password
返回不能有 password
修改可能只传 nickname
查询可能只传 userId/mobile
七、统一返回结构
微服务之间建议统一响应:
java
public class RpcResult<T> {
private boolean success;
private String code;
private String message;
private T data;
}
例如:
java
RpcResult<UserResponse> getUser(UserQueryRequest request);
八、版本兼容很重要
DTO 一旦被其他服务依赖,就不能随便改。
推荐规则:
text
新增字段:可以
删除字段:谨慎
改字段类型:禁止
改字段含义:禁止
字段重命名:基本等于破坏兼容
如果必须大改:
text
/api/v2/user/query
UserQueryV2Request
UserV2Response
九、订单服务调用用户服务示例
java
@Service
public class OrderService {
private final UserClient userClient;
public OrderService(UserClient userClient) {
this.userClient = userClient;
}
public void createOrder(Long userId) {
RpcResult<UserResponse> result =
userClient.getUser(new UserQueryRequest(userId));
if (!result.isSuccess()) {
throw new RuntimeException("查询用户失败");
}
UserResponse user = result.getData();
// 创建订单逻辑
}
}
十、推荐目录结构
text
user-api
├── client
│ └── UserClient.java
├── request
│ └── UserQueryRequest.java
├── response
│ └── UserResponse.java
└── result
└── RpcResult.java
user-service
├── controller
├── service
├── domain
├── mapper
└── converter
order-service
├── controller
├── service
└── client
一句话总结
微服务 DTO 是服务契约,不是数据库对象;Feign/RPC 接口要用独立 API 模块维护 Request/Response,并注意版本兼容。