.NET Core中的HttpClientFactory类用法详解

.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技术站

(0)
上一篇 2023年6月3日
下一篇 2023年6月3日

相关文章

  • 聊聊Unity 自定义日志保存的问题

    针对“聊聊Unity自定义日志保存的问题”,我可以提供以下完整攻略: 1. 了解Unity自带的日志系统 Unity自己的日志系统提供了五个级别的日志输出,分别是:Log、Warning、Error、Assert和Exception。日志输出的级别可以通过Debug.unityLogger.filterLogType属性来控制。我们可以通过在代码中使用Deb…

    C# 2023年5月15日
    00
  • 浅谈C#中Action和Func回调的常用方式

    下面是详细讲解“浅谈C#中 Action 和 Func 回调的常用方式” 的完整攻略。 什么是回调函数 回调函数是一种常见的程序设计模式,用于将一个函数作为参数传递给另一个函数。在调用这个另一个函数时,它将执行传递的函数作为一部分操作。这种方法被称为“回调”功能。 C# 中的回调 C# 中的回调是通过委托实现的。一个委托是一个类型,它持有对一个或多个方法的引…

    C# 2023年5月15日
    00
  • C#中的位操作小结

    让我来给您详细讲解“C#中的位操作小结”的完整攻略。 一、概述 C#中的位操作是指可以直接打开和操纵整数的各个位的操作,它是一种非常高效和灵活的算法。在C#中,位操作可以方便地完成各种数据的处理和转换,如颜色值、文件属性、位图、掩码等等。 二、位操作运算符 C#中常用的位操作运算符有以下几种: & 按位与:将两个操作数对应的位进行与操作,结果为1的位…

    C# 2023年6月7日
    00
  • C#中efcore-ShardingCore呈现“完美”分表

    我会详细讲解“C#中efcore-ShardingCore呈现‘完美’分表”的完整攻略,并包含两条示例说明。 ShardingCore 什么是ShardingCore? ShardingCore是一个基于EF Core的分表库,它提供了完美的分表功能,欢迎大家去GitHub上了解更多信息。 ShardingCore分表的实现方式 ShardingCore实现…

    C# 2023年5月31日
    00
  • timespan使用方法详解

    TimeSpan使用方法详解 什么是TimeSpan? TimeSpan是.NET Framework中表示时间间隔的一个结构体,它用于表示两个时间点之间的时间间隔,或一段时间的持续时间。 TimeSpan包括天数、小时数、分钟数、秒数和毫秒数,可以使用各种方式构造TimeSpan实例。TimeSpan在.NET平台中被广泛用于处理时间。 在代码中创建Tim…

    C# 2023年6月1日
    00
  • C#四种计时器Timer的区别和用法

    C#四种计时器Timer的区别和用法 在C#编程中,计时器是很常用的功能。在.NET Framework中,提供了四种不同的计时器Timer。本文将详细讲解这四种计时器的区别和用法。 1. System.Timers.Timer System.Timers.Timer是继承自System.ComponentModel.Component类的一个计时器。它在间…

    C# 2023年6月1日
    00
  • c#继承中的函数调用实例

    下面是针对”C#继承中的函数调用实例”的完整攻略: 概述 在C#中,继承是一种非常常见的实现代码重用和减少冗余的方式。在子类中可以重写父类中的方法,也可以从父类中继承方法。当子类继承父类的方法时,可能会出现相同名称的方法,因此在调用方法时要注意调用哪个方法。这里就介绍在继承中如何调用不同层次的方法。 基本概念 在C#中,继承是一种创建新类的机制,新类可以继承…

    C# 2023年6月8日
    00
  • C#中标准的IDispose模式代码详解

    C#中标准的IDispose模式代码详解 什么是IDispose模式 IDispose模式是一个资源管理模式,其目的是让开发者预先为对象的清理操作做好准备,从而保证应用程序的高效和正确性。IDispose模式的核心接口是IDisposable,其定义在System命名空间中。 IDispose模式的基本用法 IDispose模式的基本用法是通过实现IDisp…

    C# 2023年6月2日
    00
合作推广
合作推广
分享本页
返回顶部