JNPF 远程请求代理
📅 2026/7/23 15:03:24
👁️ 阅读次数
📝 编程学习
远程请求代理
一、核心功能
远程请求代理是 JNPF 框架提供的 HTTP 请求封装系统,支持通过接口定义远程 API 调用,无需手动编写 HTTP 请求代码。
1.1 核心价值
- 接口化定义:通过接口定义远程 API,自动生成 HTTP 请求代码
- 依赖注入:支持通过 DI 容器注入远程服务接口
- 拦截器支持:支持请求和响应拦截器,实现统一的请求处理
- 重试机制:支持请求重试,提高系统可靠性
- 配置灵活:支持多种配置方式,满足不同场景需求
二、实现原理
2.1 接口定义
通过定义接口和特性标记远程 API:
[Client("https://api.example.com")]publicinterfaceIUserApi{[Get("/users/{id}")]Task<UserInfo>GetUserInfo(stringid);[Post("/users")]Task<UserInfo>CreateUser([Body]UserInfouser);[Put("/users/{id}")]Task<UserInfo>UpdateUser(stringid,[Body]UserInfouser);[Delete("/users/{id}")]TaskDeleteUser(stringid);}2.2 动态代理
框架使用DispatchProxy动态生成接口实现:
publicclassHttpDispatchProxy:DispatchProxy,IHttpDispatchProxy{publicIEventPublisherEventPublisher{get;set;}protectedoverrideobjectInvoke(MethodInfotargetMethod,object[]args){// 解析接口方法和参数varhttpMethod=targetMethod.GetCustomAttribute<HttpMethodBaseAttribute>();varpath=httpMethod.Path;varbody=args.FirstOrDefault(a=>a?.GetType().GetCustomAttribute<BodyAttribute>()!=null);// 构建 HTTP 请求varrequest=newHttpRequestMessage(httpMethod.HttpMethod,path);request.Content=newJsonContent(body);// 发送请求varresponse=_httpClient.SendAsync(request).Result;// 解析响应returnresponse.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")]publicinterfaceIUserApi{[Get("/users")]Task<List<UserInfo>>GetUserList([QueryString]intpageIndex=1,[QueryString]intpageSize=10);[Get("/users/{id}")]Task<UserInfo>GetUserInfo(stringid);[Post("/users")]Task<UserInfo>CreateUser([Body]UserInfoInputuser);[Put("/users/{id}")]Task<UserInfo>UpdateUser(stringid,[Body]UserInfoInputuser);[Delete("/users/{id}")]TaskDeleteUser(stringid);[Get("/users/search")]Task<List<UserInfo>>SearchUsers([QueryString]stringkeyword);}3.2 注册远程服务
在Startup.cs中注册:
services.AddRemoteRequest();services.AddHttpClient<IUserApi>();3.3 注入并使用
publicclassUserService{privatereadonlyIUserApi_userApi;publicUserService(IUserApiuserApi){_userApi=userApi;}publicasyncTask<UserInfo>GetUserInfo(stringuserId){returnawait_userApi.GetUserInfo(userId);}publicasyncTask<UserInfo>CreateUser(UserInfoInputuser){returnawait_userApi.CreateUser(user);}}四、特性说明
4.1 HTTP 方法特性
| 特性 | 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接口自定义拦截器:
publicclassAuthInterceptor:IHttpInterceptor{publicTaskOnRequestAsync(HttpRequestMessagerequest){// 在请求发送前添加认证头request.Headers.Authorization=newAuthenticationHeaderValue("Bearer","token");returnTask.CompletedTask;}publicTaskOnResponseAsync(HttpResponseMessageresponse){// 在响应返回后处理if(!response.IsSuccessStatusCode){thrownewException("请求失败");}returnTask.CompletedTask;}}注册拦截器:
[Interceptor(typeof(AuthInterceptor))][Client("https://api.example.com")]publicinterfaceIUserApi{}6.2 重试机制
使用[RetryPolicy]特性配置重试策略:
[RetryPolicy(Count=3,Timeout=5000)][Client("https://api.example.com")]publicinterfaceIUserApi{}6.3 异步请求
接口方法默认异步执行:
publicinterfaceIUserApi{[Get("/users/{id}")]Task<UserInfo>GetUserInfo(stringid);}6.4 同步请求
也支持同步请求:
publicinterfaceIUserApi{[Get("/users/{id}")]UserInfoGetUserInfo(stringid);}6.5 文件上传
支持文件上传:
publicinterfaceIFileApi{[Post("/upload")]Task<UploadResult>UploadFile([FormField]stringfileName,[FormField]HttpFilefile);}6.6 批量请求
支持批量请求:
publicinterfaceIBatchApi{[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,自动生成 HTTP 请求代码
- 动态代理:使用
DispatchProxy动态生成接口实现,无需手动编写请求代码 - 依赖注入:支持通过 DI 容器注入远程服务接口
- 拦截器支持:支持请求和响应拦截器,实现统一的请求处理
- 重试机制:支持请求重试,提高系统可靠性
这种设计使得远程 API 调用更加简洁和便捷,提高了开发效率和代码可维护性。
编程学习
技术分享
实战经验