.NET Core中的HttpClientFactory类用法详解
在.NET Core中,使用HttpClient发出Http请求的场景非常普遍,而且HttpClient由于某些原因并不是线程安全的,所以我们通常需要注意HttpClient的生命周期和使用方式。HttpClientFactory则为我们提供了方便的HttpClient管理机制。
HttpClientFactory介绍
HttpClientFactory是在.NET Core 2.1释放的,不仅能对HTTP传输优化,而且能从内存池中请求和重复利用HTTP连接。它还提供了以下优点:
-
通过命名HttpClient实现可配置的强类型HttpClient实例。
-
对每个处理程序或HTTP消息处理管道(handler)进行注册,使这些处理程序可以轻松地重用并注入整个应用程序中其他地方的不同HTTP客户端。
-
支持异步HttpClient过滤器(
DelegatingHandler
),这样您就可以将跨HttpClient共享的通用行为(例如认证)实现在单个位置,从而使您的代码更加易于开发和维护。
HttpClientFactory用法详解
注入HttpClientFactory
要使用HttpClientFactory,我们首先需要将其注入到我们的DI容器中。在ASP.NET Core中,我们只需要在Startup.cs文件的ConfigureServices
方法中进行如下配置即可:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient();
//...
}
创建HttpClient实例
在HttpClientFactory中创建HttpClient实例的方式非常简单,我们只需要调用IHttpClientFactory.CreateClient
方法即可创建HttpClient实例。
public class MyService
{
private readonly HttpClient _httpClient;
//注入IHttpClientFactory
public MyService(IHttpClientFactory httpClientFactory)
{
_httpClient = httpClientFactory.CreateClient();
}
public async Task DoSomeJobAsync()
{
var response = await _httpClient.GetAsync("http://www.baidu.com");
response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsStringAsync();
//...
}
}
命名HttpClient实例
有时我们需要创建多个HttpClient实例并注入到不同的服务中,这时我们可以使用IHttpClientFactory.CreateClient(Name)
方法来为HttpClient实例命名并创建。
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient("GitHub", client => {
client.BaseAddress = new Uri("https://api.github.com/");
client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
});
services.AddHttpClient("Bing", client =>
{
client.BaseAddress = new Uri("https://cn.bing.com");
});
//...
}
public class MyService
{
private readonly HttpClient _gitHubHttpClient;
private readonly HttpClient _bingHttpClient;
//注入IHttpClientFactory
public MyService(IHttpClientFactory httpClientFactory)
{
_gitHubHttpClient = httpClientFactory.CreateClient("GitHub");
_bingHttpClient = httpClientFactory.CreateClient("Bing");
}
public async Task DoSomeJobAsync()
{
//使用_gitHubHttpClient发送请求
var gitHubResponse = await _gitHubHttpClient.GetAsync("/repos/aspnet/AspNetCore");
gitHubResponse.EnsureSuccessStatusCode();
var gitHubContent = await gitHubResponse.Content.ReadAsStringAsync();
//...
//使用_bingHttpClient发送请求
var bingResponse = await _bingHttpClient.GetAsync("/");
bingResponse.EnsureSuccessStatusCode();
var bingContent = await bingResponse.Content.ReadAsStringAsync();
//...
}
}
配置HttpClient的Handler
HttpClient可以使用自定义的HttpMessageHandler实例来处理HTTP请求和响应,HttpClientFactory允许我们为每个HttpClient配置默认的处理程序。下面使用UseDefaultHttpHandler()
方法来配置默认的处理程序:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<AuthorizationMessageHandler>();
services.AddHttpClient("GitHub", client => {
client.BaseAddress = new Uri("https://api.github.com/");
client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
}).AddHttpMessageHandler<AuthorizationMessageHandler>().UseDefaultHttpHandler();
//...
}
HttpClientFactory使用内置的HttpClientHandler作为默认处理程序,它使用内存池复用HTTP连接以提高性能。
添加HttpClient过滤器(DelegatingHandler)
HttpClient过滤器(DelegatingHandler)允许我们在请求和响应期间执行自定义逻辑,例如添加请求标头、修改请求/响应、日志记录等。示例中使用AddHttpMessageHandler
方法添加了一个自定义的AuthorizationMessageHandler。可以添加多个过滤器,它们以注册的顺序依次执行。
public class AuthorizationMessageHandler : DelegatingHandler
{
private readonly IConfiguration _configuration;
public AuthorizationMessageHandler(IConfiguration configuration)
{
_configuration = configuration;
}
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Headers.Add("Authorization", $"Bearer {_configuration["ApiKey"]}");
return base.SendAsync(request, cancellationToken);
}
}
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<AuthorizationMessageHandler>();
services.AddHttpClient("GitHub", client => {
client.BaseAddress = new Uri("https://api.github.com/");
client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
}).AddHttpMessageHandler<AuthorizationMessageHandler>();
//...
}
HttpClient的生命周期
HttpClientFactory使用从库中的HttpClient实例来处理HTTP请求和响应。默认情况下,每次调用IHttpClientFactory.CreateClient
都会创建一个新的HttpClient实例。 HttpClientFactory使用以下生命周期跟踪每个HttpClient实例的状况。
-
Transient: 瞬时生命周期在每次依赖注入时生成新的实例。
-
Scoped: 在HTTP请求期间的范围内始终相同的实例,该范围始于
HttpRequestMessage
的创建,贯穿整个HTTP请求, 直到HTTP响应返回到客户端HTTP处理管道的末端为止,随后释放HttpClient实例。 -
Singleton: 整个应用程序生命周期内始终有一个共用的单例实例。
public class MyService
{
private readonly HttpClient _httpClient;
//注入IHttpClientFactory
public MyService(IHttpClientFactory httpClientFactory)
{
_httpClient = httpClientFactory.CreateClient(); // Transient
//_httpClient = httpClientFactory.CreateClient("client_name"); // Transient
//_httpClient = httpClientFactory.CreateClient(new Uri("http://localhost:5000"));// Transient
//_httpClient = httpClientFactory.CreateClient("client_name"); // Scoped
//_httpClient = httpClientFactory.CreateClient("client_name"); // Singleton
}
public async Task DoSomeJobAsync()
{
var response = await _httpClient.GetAsync("http://www.baidu.com");
response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsStringAsync();
//...
}
}
示例1:使用HttpClientFactory进行文件下载
下面我们通过一个示例来演示如何使用HttpClientFactory进行文件下载。
public class DownloadService
{
private readonly HttpClient _httpClient;
public DownloadService(IHttpClientFactory httpClientFactory)
{
_httpClient = httpClientFactory.CreateClient();
}
public async Task DownloadFileAsync(string url, string targetPath)
{
using (var response = await _httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
{
response.EnsureSuccessStatusCode();
using (var stream = await response.Content.ReadAsStreamAsync())
{
using (var fileStream = new FileStream(targetPath, FileMode.Create, FileAccess.Write, FileShare.None, 8192, true))
{
await stream.CopyToAsync(fileStream);
}
}
}
}
}
在上面的示例中,我们定义了一个DownloadService类,它将IHttpClientFactory注入到构造函数中并使用CreateClient方法来创建HttpClient实例。然后我们使用HttpResponseMessage返回的ResponseContent流和FileStream来下载文件。
示例2:使用HttpClientFactory进行Http请求
下面我们通过一个示例来演示如何使用HttpClientFactory进行Http请求。
public class GithubService
{
private readonly HttpClient _httpClient;
public GithubService(IHttpClientFactory httpClientFactory)
{
_httpClient = httpClientFactory.CreateClient("GitHub");
}
public async Task<string> GetGithubReposAsync(string owner, string repoName)
{
var response = await _httpClient.GetAsync($"/repos/{owner}/{repoName}");
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
在上面的示例中,我们使用了根据名称为GitHub的HttpClient,然后使用这个HttpClient来向GitHub平台发送请求获取该用户仓库信息。
总结
HttpClientFactory是一个非常有用的库,它可以帮助我们更优雅地使用HttpClient,在使用中我们应该注意生命周期的选择和HttpClient的使用方式,从而更好地应对不同的场景。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:.NET Core中的HttpClientFactory类用法详解 - Python技术站