远程请求代理
一、核心功能
远程请求代理是 JNPF 框架提供的 HTTP 请求封装系统,支持通过接口定义远程 API 调用,无需手动编写 HTTP 请求代码。
1.1 核心价值
- 接口化定义:通过接口定义远程 API,自动生成 HTTP 请求代码
- 依赖注入:支持通过 DI 容器注入远程服务接口
- 拦截器支持:支持请求和响应拦截器,实现统一的请求处理
- 重试机制:支持请求重试,提高系统可靠性
- 配置灵活:支持多种配置方式,满足不同场景需求
二、实现原理
2.1 接口定义
通过定义接口和特性标记远程 API:
[Client("https://api.example.com")]
public interface IUserApi
{
[Get("/users/{id}")]
Task<UserInfo> GetUserInfo(string id);
[Post("/users")]
Task<UserInfo> CreateUser([Body] UserInfo user);
[Put("/users/{id}")]
Task<UserInfo> UpdateUser(string id, [Body] UserInfo user);
[Delete("/users/{id}")]
Task DeleteUser(string id);
}
2.2 动态代理
框架使用 DispatchProxy 动态生成接口实现:
public class HttpDispatchProxy : DispatchProxy, IHttpDispatchProxy
{
public IEventPublisher EventPublisher { get; set; }
protected override object Invoke(MethodInfo targetMethod, object[] args)
{
// 解析接口方法和参数
var httpMethod = targetMethod.GetCustomAttribute<HttpMethodBaseAttribute>();
var path = httpMethod.Path;
var body = args.FirstOrDefault(a => a?.GetType().GetCustomAttribute<BodyAttribute>() != null);
// 构建 HTTP 请求
var request = new HttpRequestMessage(httpMethod.HttpMethod, path);
request.Content = new JsonContent(body);
// 发送请求
var response = _httpClient.SendAsync(request).Result;
// 解析响应
return response.Content.ReadFromJsonAsync(targetMethod.ReturnType.GenericTypeArguments[0]).Result;
}
}
2.3 请求构建
框架自动构建 HTTP 请求:
┌─────────────────────────────────────────────────────────────┐
│ 请求构建流程 │
├─────────────────────────────────────────────────────────────┤
│ 1. 解析接口方法 │
│ └── 获取 HTTP 方法和路径 │
├─────────────────────────────────────────────────────────────┤
│ 2. 解析参数 │
│ ├── 路由参数({id}) │
│ ├── 查询参数(QueryString) │
│ ├── 请求体参数(Body) │
│ └── 请求头参数(Headers) │
├─────────────────────────────────────────────────────────────┤
│ 3. 构建 HttpRequestMessage │
│ └── 设置 HTTP 方法、URL、内容、头信息 │
├─────────────────────────────────────────────────────────────┤
│ 4. 发送请求 │
│ └── 使用 HttpClient 发送请求 │
├─────────────────────────────────────────────────────────────┤
│ 5. 解析响应 │
│ └── 将响应内容反序列化为返回类型 │
└─────────────────────────────────────────────────────────────┘
三、使用示例
3.1 定义远程 API 接口
[Client("https://api.example.com")]
public interface IUserApi
{
[Get("/users")]
Task<List<UserInfo>> GetUserList([QueryString] int pageIndex = 1, [QueryString] int pageSize = 10);
[Get("/users/{id}")]
Task<UserInfo> GetUserInfo(string id);
[Post("/users")]
Task<UserInfo> CreateUser([Body] UserInfoInput user);
[Put("/users/{id}")]
Task<UserInfo> UpdateUser(string id, [Body] UserInfoInput user);
[Delete("/users/{id}")]
Task DeleteUser(string id);
[Get("/users/search")]
Task<List<UserInfo>> SearchUsers([QueryString] string keyword);
}
3.2 注册远程服务
在 Startup.cs 中注册:
services.AddRemoteRequest();
services.AddHttpClient<IUserApi>();
3.3 注入并使用
public class UserService
{
private readonly IUserApi _userApi;
public UserService(IUserApi userApi)
{
_userApi = userApi;
}
public async Task<UserInfo> GetUserInfo(string userId)
{
return await _userApi.GetUserInfo(userId);
}
public async Task<UserInfo> CreateUser(UserInfoInput user)
{
return await _userApi.CreateUser(user);
}
}
四、特性说明
4.1 HTTP 方法特性
| [Get] | GET | 获取资源 |
| [Post] | POST | 创建资源 |
| [Put] | PUT | 更新资源 |
| [Delete] | DELETE | 删除资源 |
| [Patch] | PATCH | 部分更新资源 |
| [Head] | HEAD | 获取资源头信息 |
4.2 参数特性
| [Body] | 请求体参数,序列化为 JSON |
| [QueryString] | 查询字符串参数 |
| [Headers] | 请求头参数 |
| [FormField] | 表单字段参数 |
4.3 类级别特性
| [Client] | 指定基础地址 |
| [Headers] | 指定默认请求头 |
| [Interceptor] | 指定拦截器类型 |
五、配置选项
5.1 客户端配置
在 appsettings.json 中配置:
{
"RemoteRequestSettings": {
"Clients": {
"IUserApi": {
"BaseAddress": "https://api.example.com",
"Timeout": "00:01:00",
"Headers": {
"Accept": "application/json",
"Authorization": "Bearer token"
}
}
}
}
}
5.2 客户端配置项
| BaseAddress | null | 基础地址 |
| Timeout | 00:01:00 | 请求超时时间 |
| Headers | {} | 默认请求头 |
| RetryCount | 0 | 重试次数 |
| RetryTimeout | 00:00:01 | 重试间隔 |
5.3 服务注册配置
services.AddRemoteRequest(options =>
{
options.Timeout = TimeSpan.FromSeconds(30);
options.RetryCount = 3;
options.RetryTimeout = TimeSpan.FromSeconds(5);
});
六、高级特性
6.1 拦截器
实现 IHttpInterceptor 接口自定义拦截器:
public class AuthInterceptor : IHttpInterceptor
{
public Task OnRequestAsync(HttpRequestMessage request)
{
// 在请求发送前添加认证头
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "token");
return Task.CompletedTask;
}
public Task OnResponseAsync(HttpResponseMessage response)
{
// 在响应返回后处理
if (!response.IsSuccessStatusCode)
{
throw new Exception("请求失败");
}
return Task.CompletedTask;
}
}
注册拦截器:
[Interceptor(typeof(AuthInterceptor))]
[Client("https://api.example.com")]
public interface IUserApi { }
6.2 重试机制
使用 [RetryPolicy] 特性配置重试策略:
[RetryPolicy(Count = 3, Timeout = 5000)]
[Client("https://api.example.com")]
public interface IUserApi { }
6.3 异步请求
接口方法默认异步执行:
public interface IUserApi
{
[Get("/users/{id}")]
Task<UserInfo> GetUserInfo(string id);
}
6.4 同步请求
也支持同步请求:
public interface IUserApi
{
[Get("/users/{id}")]
UserInfo GetUserInfo(string id);
}
6.5 文件上传
支持文件上传:
public interface IFileApi
{
[Post("/upload")]
Task<UploadResult> UploadFile([FormField] string fileName, [FormField] HttpFile file);
}
6.6 批量请求
支持批量请求:
public interface IBatchApi
{
[Post("/batch")]
Task<List<BatchResult>> BatchRequest([Body] List<BatchItem> items);
}
6.7 请求日志
框架自动记录请求日志:
services.AddRemoteRequest(options =>
{
options.LogEnabled = true;
});
七、核心文件
| HttpDispatchProxy.cs | HTTP 动态代理实现 |
| IHttpDispatchProxy.cs | HTTP 动态代理接口 |
| Http.cs | HTTP 请求入口类 |
| HttpRequestPart.cs | HTTP 请求部分 |
| HttpRequestPartMethods.cs | HTTP 请求方法 |
| HttpRequestPartSetters.cs | HTTP 请求设置器 |
| HttpResponseModel.cs | HTTP 响应模型 |
| RemoteRequestServiceCollectionExtensions.cs | 远程请求服务扩展方法 |
| GetAttribute.cs | GET 请求特性 |
| PostAttribute.cs | POST 请求特性 |
| PutAttribute.cs | PUT 请求特性 |
| DeleteAttribute.cs | DELETE 请求特性 |
| BodyAttribute.cs | 请求体参数特性 |
| QueryStringAttribute.cs | 查询字符串参数特性 |
| ClientAttribute.cs | 客户端特性 |
| InterceptorAttribute.cs | 拦截器特性 |
| RetryPolicyAttribute.cs | 重试策略特性 |
八、总结
远程请求代理通过接口化定义和动态代理技术,实现了简洁的远程 API 调用方式。核心设计思想:
这种设计使得远程 API 调用更加简洁和便捷,提高了开发效率和代码可维护性。






