使用方式
IHttpClientFactory 有四种模式:
基本用法
命名客户端
类型化客户端
生成的客户端
基本用法
在 Startup.ConfigureServices 方法中, 通过在 IServiceCollection 上调用 AddHttpClient 扩展方法可以注册 IHttpClientFactory
services.AddHttpClient();
注册之后可以像依赖注入 DI 似得在类中通过构造函数注入形式使用, 伪代码:
- class A
- {
- private readonly IHttpClientFactory _clientFactory;
- public A(IHttpClientFactory clientFactory)
- {
- _clientFactory = clientFactory;
- }
- Public void Use()
- {
- var request=new HttpRequestMessage(HttpMethod.Get,"www.baidu.com") ;
- var client = _clientFactory.CreateClient();
- var response = await client.SendAsync(request);
- if (response.IsSuccessStatusCode)
- {
- Branches = await response.Content.ReadAsAsync<IEnumerable<GitHubBranch>>();
- }
- else
- {
- GetBranchesError = true;
- Branches = Array.Empty<GitHubBranch>();
- }
- }
- }
命名客户端
也是在基本用法的基础上增加配置参数: 例如增加一个 baidu 下的客户端:
- services.AddHttpClient("baidu",c=>
- {
- c.BaseAddress = new Uri("https://api.baidu.com/");
- // 其他一些参数
- });
然后在使用的时候只是需要传递客户端名称就自动使用 baidu 这个地址的基础地址配置:
var client = _clientFactory.CreateClient("baidu");
类型化客户端
说的明白一点就是在使用类的构造函数中可以直接接受 HttpClient 类型, 不用在使用 IHttpClientFactory 接口的 CreateClient 方法创建, 但是首要条件就是要先创建注入类型, 然后在 ConfigureServices 方法同时注入:
services.AddHttpClient<classHttp>();
注入类型:
- public class classHttp
- {
- public HttpClient Client { get; }
- public GitHubService(HttpClient client)
- {
- client.BaseAddress = new Uri("https://api.baidu.com/");
- // 同 ConfigureServices 中一样设置一些其他参数
- Client = client;
- }
- }
生成的客户端
这个我个人理解为就是配置使用第三方库, 然后可以注入接口类型, 接口中可以写一些方法接口. 然后通过接口类直接调用接口.
个人理解: 就是类似于一个接口映射, 地址映射似得. 通过结合第三方库 (官方推荐 Refit) 实现请求一个地址别名的方式, 别名就是指定义的接口. 然后别名通过增加特性 Get("路径")或者 post(" 路径)的形式重新指向真实的请求接口地址. 通过请求这个本地接口方法实现转化请求的真实地址.
举例定义接口:
- public interface IHelloClient
- {
- [Get("/MyInterFace")]
- Task<Reply> GetMessageAsync();
- }
配置 Refit 插件:
也是和正常配置类似, 在后面增加接口的服务注入.
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddHttpClient("hello", c =>
- {
- c.BaseAddress = new Uri("http://localhost:5000");
- })
- .AddTypedClient(c => Refit.RestService.For<IHelloClient>(c));
- services.AddMvc();
- }
然后再说接口上面的 Get("/MyInterFace")方法; 这个我们就不做另一个项目就在当前项目下, 所以可以直接就在 API 项目下创建一个名为 MyInterFace 的方法.
- [ApiController]
- public class TestController : ControllerBase
- {
- [HttpGet("/")]
- public async Task<sting> MyInterFace()
- {
- return "ceshi";
- }
- }
然后就可以使用接口了:
- [ApiController]
- public class ValuesController : ControllerBase
- {
- private readonly IHelloClient _client;
- public ValuesController(IHelloClient client)
- {
- _client = client;
- }
- [HttpGet("/")]
- public async Task<ActionResult<Reply>> Index()
- {
- return await _client.GetMessageAsync();
- }
- }
在这了的_client.GetMessageAsync()方法就是调用了接口方法, 看着是调用了 GetMessageAsync 方法其实是做了映射, 映射地址就是上面特性写的 MyInterFace 方法. 通过断点也可以验证此结论. 然后不同项目下也是同一个意思, 假如我们请求百度的地址: www.baidu.com/API/b 这个接口
我们在配置出把请求地址 http://localhost:5000 改为 www.baidu.com/API, 然后再把 GetMessageAsync 方法上面的 MyInterFace 改为 b 即可.
出站请求中间件
个人理解为请求返回前处理程序, 就是继承 DelegatingHandler 派生类重写 SendAsync 方法. 在将请求传递至管道中的下一个处理程序之前执行代码:
- public class ValidateHeaderHandler : DelegatingHandler
- {
- protected override async Task<HttpResponseMessage> SendAsync(
- HttpRequestMessage request,
- CancellationToken cancellationToken)
- {
- if (!request.Headers.Contains("X-API-KEY"))
- {
- return new HttpResponseMessage(HttpStatusCode.BadRequest)
- {
- Content = new StringContent(
- "You must supply an API key header called X-API-KEY")
- };
- }
- return await base.SendAsync(request, cancellationToken);
- }
- }
然后在 ConfigureServices 中:
- services.AddTransient<ValidateHeaderHandler>();// 注册处理程序
- services.AddHttpClient("externalservice", c =>
- {
- // Assume this is an "external" service which requires an API KEY
- c.BaseAddress = new Uri("https://localhost:5000/");
- })
.AddHttpMessageHandler<ValidateHeaderHandler>();/ 注入到 http 请求管道
可以同时注册多个处理程序.
HttpClient 和生存周期
每次对 IHttpClientFactory 调用 CreateClient 都会返回一个新 HttpClient 实例. 每个命名的客户端都具有一个 HttpMessageHandler. 工厂管理 HttpMessageHandler 实例的生存期.
HttpClient 实例不是与 HttpMessageHandler 一起销毁的, HttpMessageHandler 在池中生存, 如果生命周期未到不会被销毁, 会被新的 HttpClient 实例使用.
处理程序的默认生存周期是 2 分钟, 可以通过配置修改:
- services.AddHttpClient("extendedhandlerlifetime")
- .SetHandlerLifetime(TimeSpan.FromMinutes(5));
原文有道云笔记连接: https://note.youdao.com/ynoteshare1/index.html?id=80912dd7064716428880a8e201b76a11&type=note
来源: https://www.cnblogs.com/yanbigfeg/p/11509926.html