封装网络通信应隐藏技术细节,只暴露语义明确的业务方法;所有网络相关字段设为private且不提供getter/setter;统一处理超时、重试、日志、鉴权等横切关注点;返回抽象结果类型ApiResult<T>,屏蔽底层框架差异。

在类设计中通过封装隐藏复杂的网络通信细节,关键不是把 Socket、HTTP 客户端或重试逻辑“藏起来”,而是让调用方完全不用感知底层是 TCP 还是 HTTP、是否用了连接池、有没有超时重试、是否需要鉴权头——所有这些都收进类内部,只暴露一个干净、语义明确的业务方法。
把网络相关字段和辅助逻辑设为 private
所有与网络实现强相关的成员,比如 HttpClient 实例、Base URL、认证 token、重试计数器、序列化器等,一律声明为 private。不提供 public getter/setter,也不允许外部直接操作。
- 例如:private final CloseableHttpClient httpClient; —— 外部连 new 的机会都没有
- private final String baseUrl; —— 不暴露拼接逻辑,也不让调用方自己构造 URL
- private final ObjectMapper jsonMapper; —— 序列化细节不透出,避免外部传错格式
只暴露高阶业务方法,不暴露技术动作
对外接口应描述“做什么”,而不是“怎么发请求”。比如:
- sendOrder(Order order) —— 而不是 post("/api/orders", order)
- fetchUserProfile(String userId) —— 而不是 get("/users/" + id, User.class)
- cancelSubscription(String subId) —— 内部自动加 Authorization 头、处理 401 刷新 token、记录失败日志
这些方法内部可自由切换实现:从 OkHttp 换成 WebClient,从 REST 换成 gRPC,甚至退化为本地 mock,只要返回结果类型一致,调用方代码完全不用改。
立即学习“Java免费学习笔记(深入)”;
在公共方法中统一处理横切关注点
网络调用共有的复杂性(超时、重试、错误转换、日志、监控)全部封装在方法体内,不交给使用者判断或配置:
- 超时统一设为 5 秒,不可由调用方传入;如需差异化,用不同方法名区分(如 fetchUserProfileFast() / fetchUserProfileReliable())
- 对 5xx 响应自动重试最多 2 次,失败后包装为自定义异常(如 NetworkUnavailableException),不抛出 IOException 或 ExecutionException
- 所有请求自动注入 traceId、添加 X-Request-ID,响应自动记录耗时并上报 metrics
返回结果做抽象,不暴露底层类型
不要返回 CompletableFuture<HttpResponse>、ResponseEntity<T> 或 InputStream 等框架相关类型。定义简洁的结果容器:
- public class ApiResult<T> { boolean success; T data; String errorCode; String message; }
- 调用方只关心 if (result.isSuccess()) { use(result.getData()); },无需知道是不是异步、有没有 body 解析失败
- 敏感字段(如 token、密钥)在序列化前自动脱敏,getter 中已过滤,不依赖调用方自行处理


















