.Net Core 使用IHttpClientFactory请求
实例的自定义类,该自定义类封装了通过HTTP协议调用所有终结点的逻辑。整体说明:这里主要是借助依赖注入程序,在控制台上获取需要的相关类,然后进行使用对应方法的调用。的非静态实例包装在自定义类中,并使其成为单例类。是在.Net Core 2.1引入的,它提供了一个命名,配置和创建。实例,以下是一个不错的选择。,而且可以很友好的和 DI 容器结合使用,更为灵活。实例的核心功能,并能自动管理实例的池化和
一、为什么不用HttpClient
-
HttPClient
使用完之后不会立即关闭开启网络连接时会占用底层socket
资源,但在HttpClient
调用其本身的Dispose
方法时,并不能立刻释放该资源 -
如果频繁的使用
HttpClient
,频繁的打开链接,关闭链接消耗就会很大。
二、解决方案
- 我们可以延长
HttpClient
的生命周期,比如对其建一个静态的对象
private static HttpClient Client = new HttpClient();
- 或者使用单例模式,至于你使用哪一种单例模式就看你自己了,这里就不细将了。因为这样感觉起来不是很舒服
三、HttpClientFactory
-
在
.NET Core 2.1
版本之后引入的HttpClientFactory
解决了HttpClient
的所有痛点。有了HttpClientFactory
,我们不需要关心如何创建HttpClient
,又如何释放它。通过它可以创建具有特定业务的HttpClient
,而且可以很友好的和 DI 容器结合使用,更为灵活。 -
HttpClientFactory
创建的HttpClient
,也即是HttpClientHandler
,只是这些个HttpClient
被放到了“池子”中,工厂每次在create
的时候会自动判断是新建还是复用。(默认生命周期为2min,默认的生命周期可以修改)
//修改默认的生命周期
services.AddHttpClient().SetHandlerLifetime(TimeSpan.FromMinutes(5));
四、HttpClientFactory
的使用
一、第一种使用方式
- 在
Startup.cs
中进行注册
//注册http请求服务
services.AddHttpClient();
Httphelper
请求辅助类中使用
/// <summary>
/// 注入http请求
/// </summary>
private readonly IHttpClientFactory httpClientFactory;
public HttpHelp(IHttpClientFactory _httpClientFactory)
{
httpClientFactory = _httpClientFactory;
}
// <summary>
// Get请求数据
// <para>最终以url参数的方式提交</para>
// </summary>
// <param name="parameters">参数字典,可为空</param>
// <param name="requestUri">例如/api/Files/UploadFile</param>
// <returns></returns>
public async Task < string > Get(Dictionary < string, string > parameters, string requestUri, string token)
{
//从工厂获取请求对象
var client = httpClientFactory.CreateClient();
//添加请求头
if(!string.IsNullOrWhiteSpace(token))
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
}
client.DefaultRequestHeaders.Add("Content-Type", "application/json; charset=utf-8");
//拼接地址
if(parameters != null)
{
var strParam = string.Join("&", parameters.Select(o => o.Key + "=" + o.Value));
requestUri = string.Concat(requestUri, '?', strParam);
}
client.BaseAddress = new Uri(requestUri);
return client.GetStringAsync(requestUri).Result;
}
- 然后我们在
Startup.cs
对相对的类进行注册就可以了使用了。
二、使用命名客户端
- 在
Startup.cs
中进行注册,这个注册可以存在多个。以创建名字区分
services.AddHttpClient("github", c =>
{
c.BaseAddress = new Uri("https://xxxxxxx.com/");
// Github API versioning
c.DefaultRequestHeaders.Add("Content-Type", "application/json; charset=utf-8");
// Github requires a user-agent
c.DefaultRequestHeaders.Add("Authorization", "asfasfasdsgdsfsdfsdafasfas");
});
- 使用方式和上面的一样只要
/// <summary>
/// 注入http请求
/// </summary>
private readonly IHttpClientFactory httpClientFactory;
public HttpHelp(IHttpClientFactory _httpClientFactory)
{
httpClientFactory = _httpClientFactory;
}
// <summary>
// Get请求数据
// <para>最终以url参数的方式提交</para>
// </summary>
// <param name="parameters">参数字典,可为空</param>
// <param name="requestUri">例如/api/Files/UploadFile</param>
// <returns></returns>
public async Task < string > Get(Dictionary < string, string > parameters, string requestUri, string token)
{
//从工厂获取请求对象 声明自己创建哪一个httpClient客户端
var client = httpClientFactory.CreateClient("github");
//添加请求头
if(!string.IsNullOrWhiteSpace(token))
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
}
client.DefaultRequestHeaders.Add("Content-Type", "application/json; charset=utf-8");
//拼接地址
if(parameters != null)
{
var strParam = string.Join("&", parameters.Select(o => o.Key + "=" + o.Value));
requestUri = string.Concat(requestUri, '?', strParam);
}
client.BaseAddress = new Uri(requestUri);
return client.GetStringAsync(requestUri).Result;
}
三、类型化客户端
- 创建一个类
public class HttpClienService
{
public HttpClient Client { get; }
public HttpClienService(HttpClient client)
{
client.BaseAddress = new Uri("https://xxxx.com/");
// GitHub API versioning
client.DefaultRequestHeaders.Add("Authorization",
"xxxxxxxxxxxx");
// GitHub requires a user-agent
client.DefaultRequestHeaders.Add("Content-Type",
"application/json; charset=utf-8");
Client = client;
}
//这个下面就是编写自己方法,进行调用
}
- 在
Startup.cs
中进行注册,这个注册可以存在多个。
services.AddHttpClient<classHttp>();
//注册之后,使用依赖注入的方式进行注入,进行使用。
IHttpClientFactory
利用IHttpClientFactory
可以无缝创建HttpClient
实例,避免手动管理它们的生命周期。
当使用ASP.Net Core开发应用程序时,可能经常需要通过HttpClient
调用WebAPI的方法以检查终结点是否正常工作。要实现这一点,通常需要实例化HttpClient
并使用该实例来调用你的方法。但是直接使用HttpClient
也有一些缺点,主要与手动管理实例的生命周期有关。
你可以使用IHttpClientFactory
创建HttpClient
来避免这些问题。IHttpClientFactory
是在.Net Core 2.1引入的,它提供了一个命名,配置和创建HttpClient
实例的核心功能,并能自动管理实例的池化和生命周期。
为什么使用IHttpClientFactory
?
尽管HttpClient
没有直接实现IDisposable
接口,但它扩展了System.Net.Http
。HttpMessageInvoker
,这个类实现了IDisposable
。然而,当使用HttpClient
实例时,你不应该手动操作释放它们。尽管可以在HttpClient
实例上调用Dispose
方法,但不推荐这样做。
应该怎么做呢?一种选择是使HttpClient
静态化,或者将HttpClient
的非静态实例包装在自定义类中,并使其成为单例类。但是更好的替代方法是使用IHttpClientFactory
来生成HttpClient
的实例,然后使用该实例来调用操作方法。
当你释放HttpClient
实例时,连接将保持打开状态长达4分钟。此外,可以在任何时间点打开socket
的数量是有限制的——不能同时打开太多socket
。因此,当使用太多HttpClient
实例时,可能会耗尽socket
。
这就是IHttpClientFactory
的意义所在。你可以通过利用IHttpClientFactory
来创建用于调用HTTP API方法的HttpClient
实例,以避免HttpClient
所面临的问题。在ASP.NET Core中实现IHttpClientFactory
的主要目标是为了确保使用工厂模式创建HttpClient
实例的同时避免socket
耗尽。
IHttpClientFactory
和HttpClientFactory
IHttpClientFactory
是一个由DefaultHttpClientFactory
类实现的接口,这是一个工厂模式。DefaultHttpClientFactory
实现了IHttpClientFactory
和IHttpMessageHandlerFactory
接口。IHttpClientFactory
提供了ASP.NET Core对创建、缓存和处理HttpClient
实例提供了出色的内置支持。
请注意,HttpClientFactory
只是一个帮助类,用于创建使用提供的处理程序配置的HttpClient
实例。这个类有以下方法:?
Create(DelegatingHandler[])
Create(HttpMessageHandler,DelegatingHandler[])
CreatePipeline(HttpMessageHandler,IEnumerable<DelegatingHandler>)
重载的HttpClientFactory
类的Create
方法看起来像这样:?
public static HttpClient Create(params DelegatingHandler[] handlers)
{
return Create(new HttpClientHandler(), handlers);
}
public static HttpClient Create(HttpMessageHandler innerHandler, params DelegatingHandler[] handlers)
{
HttpMessageHandler pipeline = CreatePipeline(innerHandler, handlers);
return new HttpClient(pipeline);
}
引入HttpClientFactory
和IHttpClientFactory
是为了更好地管理HttpMessageHandler
实例的生命周期。
在ASP.NET Core中注册IHttpClientFactory
实例
你可以在Startup
类的ConfigureServices
方法中,通过调用IServiceCollection
实例上的AddHttpClient
扩展方法注册一个IHttpClientFactory
类型的实例,如下:?
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddHttpClient();
}
将IHttpClientFactory
实例注入到控制器
可以通过如下代码将将IHttpClientFactory
实例注入到控制器:?
public class HomeController : Controller
{
private IHttpClientFactory _httpClientFactory;
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger,
IHttpClientFactory httpClientFactory)
{
_logger = logger;
_httpClientFactory = httpClientFactory;
}
}
在Action
中调用HttpClient
要通过使用IHttpClientFactory
创建HttpClient
,应该调用CreateClient
方法。一旦HttpClient
实例可用,就可以在HomeController
类的index
方法中使用以下代码来调用ValuesController
类的Get
方法。
public async Task<IActionResult> Index()
{
HttpClient httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = new Uri("http://localhost:5000/");
var response = await httpClient.GetAsync("/api/values");
string str = await response.Content.ReadAsStringAsync();
List<string> data = JsonSerializer.Deserialize<List<string>>(str);
return View(data);
}
使用IHttpClientFactory
在ASP.NET Core中创建和管理HttpClient
实例
有几种方法可以在应用程序中使用IHttpClientFactory
。这包括直接使用IHttpClientFactory
、使用命名client
和类型client
。
基本的或一般的使用模式,即直接使用IHttpClientFactory
。请参考“注册一个IHttpClientFactory
实例”一节,该节讨论了如何注册HttpClient
实例。
如果你想使用不同配置的HttpClient
实例,以下是一个不错的选择。下面的代码片段说明了如何创建。
services.AddHttpClient("github", c =>
{
c.BaseAddress = new Uri("https://api.github.com/");
c.DefaultRequestHeaders.Add("Accept",
"application/vnd.github.v3+json");
c.DefaultRequestHeaders.Add("User-Agent", "This is a test user agent");
});
第二种方法是使用包装了HttpClient
实例的自定义类,该自定义类封装了通过HTTP协议调用所有终结点的逻辑。下面的代码片段说明了如何定义自定义HttpClient
类。
public class ProductService : IProductService
{
private IHttpClientFactory _httpClientFactory;
private readonly HttpClient _httpClient;
private readonly string _baseUrl = "http://localhost:1810/";
public ProductService(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<Catalog> GetAllProducts()
{
_httpClient = _httpClientFactory.CreateClient();
_httpClient.BaseAddress = new Uri(_baseUrl);
var uri = "/api/products";
var result = await _httpClient.GetStringAsync(uri);
return JsonConvert.DeserializeObject<Product>(result);
}
}
通过以下代码注册自定义的client
:
services.AddHttpClient<IProductService, ProductService>();
将MessageHandler
添加到命名管道中
MessageHandler
是扩展自HttpMessageHandler
类,它可以接受HTTP请求并返回HTTP响应。如果你想构建自己的MessageHandler
,你应该创建一个继承DelegatingHandler
的类。
你可以将HttpMessageHandler
添加到请求处理管道中。可以在Startup
类的ConfigureServices
方法中使用以下代码将HttpMessageHandler
添加到管道中。
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient("github", c =>
{
c.BaseAddress = new Uri("https://api.github.com/");
})
.AddHttpMessageHandler<DemoHandler>();
services.AddTransient<DemoHandler>();
}
IHttpClientFactory
是一个自.net Core 2.1以来就可用的工厂类。如果你使用IHttpClientFactory
来创建HttpClient
实例,那么底层HttpClientMessagehandler
实例的池化和生命周期将自动管理。IHttpClientFactory
还负责处理一些常见问题,比如日志记录。
控制台中使用HttpClientFactory
整体说明:这里主要是借助依赖注入程序,在控制台上获取需要的相关类,然后进行使用对应方法的调用
(1).首先需要添加依赖注入的程序集【Microsoft.Extensions.DependencyInjection
】
(2).添加所需组件对应的程序集,并进行Addxxxx
(3).创建Provicder
(4).利用Provider
调用GetService
获取对应对象
HttpClientFactory
添加程序集:【Microsoft.Extensions.Http
】
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddHttpClient();
var serviceProvider = serviceCollection.BuildServiceProvider();
//var serviceProvider = new ServiceCollection().AddHttpClient().BuildServiceProvider(); //等价于以上三句话
IHttpClientFactory httpClientFactory = serviceProvider.GetService < IHttpClientFactory > ();
//下面是使用
string url2 = "http://XXX:8055/Home/SendAllMsg";
var client = httpClientFactory.CreateClient();
var content = new StringContent("msg=123", Encoding.UTF8, "application/x-www-form-urlencoded");
var response = client.PostAsync(url2, content).Result;
string result = "";
if(response.IsSuccessStatusCode)
{
result = response.Content.ReadAsStringAsync().Result;
}
}
更多推荐
所有评论(0)