You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求创建API/WebAPI客户端包的设计模式与指导方案

WebAPI客户端库设计指南与模式

核心设计原则

  • 优先做好封装:把HTTP方法、请求头、序列化规则这些通信细节全藏起来,使用者只需要调用业务相关的方法,不用管底层怎么实现
  • 极简配置:只对外开放必要的配置项(比如API基础地址、超时时间、认证密钥),其他默认规则由你统一管控
  • 保持一致性:所有API方法的命名、参数结构、返回值格式统一,降低使用者的学习成本
  • 预留扩展点但把控核心:可以给使用者留自定义拦截器、序列化器的口子,但核心通信逻辑必须由你控制,不能让使用者随意修改

常用设计模式

1. 门面模式(Facade)

提供一个统一的入口类(比如CompanyApiClient),把分散的业务API(用户、订单、权限等)聚合起来,也可以按业务拆分成子门面(UserApiClient、OrderApiClient),让使用者调用起来更直观。
示例代码:

public class CompanyApiClient
{
    private readonly UserApiClient _userClient;
    private readonly OrderApiClient _orderClient;

    public CompanyApiClient(HttpClient httpClient)
    {
        _userClient = new UserApiClient(httpClient);
        _orderClient = new OrderApiClient(httpClient);
    }

    // 直接暴露子模块方法,或者提供子模块的访问属性
    public Task<UserDto> GetUserById(int id) => _userClient.GetById(id);
    public Task<OrderDto> CreateOrder(CreateOrderRequest request) => _orderClient.Create(request);
}

2. 适配器模式(Adapter)

如果内部API混用了不同通信协议(比如部分REST、部分gRPC),用适配器把不同的实现统一成相同的对外接口,使用者不用关心底层协议差异。
示例代码:

// 统一对外接口
public interface IUserApi
{
    Task<UserDto> GetById(int id);
}

// REST协议实现
public class RestUserApi : IUserApi
{
    private readonly HttpClient _httpClient;
    public RestUserApi(HttpClient httpClient) => _httpClient = httpClient;

    public async Task<UserDto> GetById(int id)
    {
        var response = await _httpClient.GetAsync($"users/{id}");
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadFromJsonAsync<UserDto>();
    }
}

// 未来换成gRPC时,只需要新增适配器,对外接口不变
public class GrpcUserApi : IUserApi
{
    private readonly UserService.UserServiceClient _client;
    public GrpcUserApi(UserService.UserServiceClient client) => _client = client;

    public async Task<UserDto> GetById(int id)
    {
        var response = await _client.GetUserByIdAsync(new GetUserByIdRequest { Id = id });
        return MapToUserDto(response.User);
    }
}

3. 拦截器模式(Interceptor)

用来统一处理请求前后的通用逻辑,比如自动加认证头、记录请求日志、统一异常处理、重试机制,这部分完全由你管控,使用者不用操心。
示例代码(以.NET HttpClient为例):

public class ApiRequestHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // 请求前:自动添加统一认证头
        request.Headers.Add("X-Company-Api-Key", GetApiKeyFromConfig());
        
        // 发送请求
        var response = await base.SendAsync(request, cancellationToken);
        
        // 请求后:统一处理异常
        if (!response.IsSuccessStatusCode)
        {
            var errorContent = await response.Content.ReadAsStringAsync();
            throw new CompanyApiException(response.StatusCode, errorContent);
        }
        
        return response;
    }
}

具体实现步骤

  1. 统一DTO模型:把API的请求/响应数据模型都放在客户端库里,确保所有使用者用的是同一套结构,避免版本不一致导致的问题
  2. 简化配置管理:提供简洁的配置方式,推荐用依赖注入传入配置对象,示例:
    public class CompanyApiConfig
    {
        public string BaseUrl { get; set; }
        public int TimeoutSeconds { get; set; } = 30;
        public string ApiKey { get; set; }
    }
    
  3. 集成依赖注入:针对主流框架(比如.NET、Spring Boot)提供DI扩展方法,让使用者一行代码就能完成注入,示例:
    public static class ServiceCollectionExtensions
    {
        public static IServiceCollection AddCompanyApiClient(this IServiceCollection services, Action<CompanyApiConfig> configure)
        {
            var config = new CompanyApiConfig();
            configure(config);
            
            services.AddSingleton(config);
            services.AddHttpClient<CompanyApiClient>(client =>
            {
                client.BaseAddress = new Uri(config.BaseUrl);
                client.Timeout = TimeSpan.FromSeconds(config.TimeoutSeconds);
            }).AddHttpMessageHandler<ApiRequestHandler>();
            
            services.AddTransient<ApiRequestHandler>();
            return services;
        }
    }
    
  4. 自定义异常类型:封装统一的异常(比如CompanyApiException),包含API返回的错误码和消息,方便使用者捕获和处理
  5. 内置文档与示例:在库的README里写清楚快速开始步骤、方法说明、常见问题,比如:

    快速开始:

    1. 安装包:Install-Package Company.Api.Client
    2. 在Startup中注入:
      services.AddCompanyApiClient(config =>
      {
          config.BaseUrl = "https://api.company.com";
          config.ApiKey = "your-api-key";
      });
      
    3. 在业务类中调用:
      private readonly CompanyApiClient _apiClient;
      public MyService(CompanyApiClient apiClient) => _apiClient = apiClient;
      
      public async Task DoSomething()
      {
          var user = await _apiClient.GetUserById(123);
          // 业务逻辑
      }
      

最佳实践

  • 版本同步:客户端库版本和API版本保持对应,比如库版本v1.2.3对应API的v1版本,API升级到v2时发布新的客户端库版本(或者支持多版本切换)
  • 向后兼容:尽量不修改现有方法的签名,新增功能用新方法,确保老版本使用者不用改代码
  • 测试覆盖:在客户端库里写集成测试,调用真实API(或Mock),确保通信逻辑正确,也方便你在API变更时验证兼容性
  • 隐藏底层细节:别把HttpClient这类底层对象暴露给使用者,防止他们修改你管控的通信规则

内容的提问来源于stack exchange,提问作者Mate

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 00:15:36