.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日

相关文章

  • 使用C#连接SQL Server的详细图文教程

    我很乐意为您提供“使用C#连接SQL Server的详细图文教程”攻略。 简介 在使用C#开发应用程序时,经常需要与数据库进行交互,而SQL Server是一个广泛使用的关系数据库管理系统。这里将为您提供使用C#连接SQL Server的详细图文教程,以帮助您完成这项任务。 步骤 步骤1:安装SQL Server和SQL Server Management …

    C# 2023年6月3日
    00
  • C#之字符串截取–Regex.Match使用

    C#之字符串截取–Regex.Match使用 在C#中,字符串截取是一项常见操作。Regex.Match()方法提供了一种强大的方式来根据正则表达式截取和匹配字符串。本文将介绍Regex.Match()方法的使用方法,包括声明、基本语法和两条示例说明。 声明 public static System.Text.RegularExpressions.Matc…

    C# 2023年6月6日
    00
  • C#多线程系列之任务基础(一)

    我会为你详细介绍“C#多线程系列之任务基础(一)”的完整攻略。 什么是多线程? 多线程是一种并发编程的思想,可以在 CPU 繁忙的时候,运行不同的线程,从而达到提高 CPU 使用率的目的。对于 I/O bound 任务(如等待用户输入、读写文件等),多线程同样可以提高任务的效率,因为不同的线程可以异步运行,而不需要等待其它 I/O 操作。 任务是什么? 在 …

    C# 2023年5月15日
    00
  • C# Directory.GetFiles(string path):获取指定目录下的所有文件路径

    Directory.GetFiles(string path) 是C#中的一个静态方法,它返回指定目录中文件的名称,包括该目录中的所有子目录。它是 DirectoryInfo 类的一个实例方法 GetFiles 的静态等效方法。 方法签名 public static string[] GetFiles(string path); public static …

    C# 2023年4月19日
    00
  • C#一个方法返回多个值示例

    下面是关于C#一个方法返回多个值的完整攻略。 什么是返回多个值的方法 C#的函数(方法)通常只能返回一个值,但是有时候一个函数需要返回多个值,此时就需要使用一些特殊的方式实现返回多个值的方法,例如使用元组(Tuple)、结构体(Struct)或者自定义类型等方式。 使用元组实现一个方法返回多个值 元组是用来组合多个数据项的一种数据结构。在C#7中,引入了元组…

    C# 2023年5月15日
    00
  • C# String.Compare()方法: 比较两个指定的字符串并返回它们之间的关系

    String.Compare() 是C#中用于比较两个字符串的方法。该方法将比较两个字符串,并根据其字典排序顺序返回一个整数值。返回的整数值将指示字符串是否相等,以及它们在字典排序中的相对位置。 方法签名 以下是方法的签名: public static int Compare(string strA, string strB, bool ignoreCase…

    C# 2023年4月19日
    00
  • C#简单获取时间差的小例子

    下面我来详细讲解如何实现“C#简单获取时间差的小例子”。 目录 问题描述 解决方案 使用TimeSpan获取时间差 使用DateTime的Subtract方法获取时间差 总结 问题描述 在编写C#程序时,我们常常需要获取时间差,比如计算某个操作执行的时间、计算两个时间点之间的时长等等。那么,如何快速、简单地获取时间差呢? 解决方案 以下是两种使用C#获取时间…

    C# 2023年6月1日
    00
  • IIS下调用证书出现异常的解决方法 (C#)

    针对“IIS下调用证书出现异常的解决方法(C#)”这个问题,我来给出一份完整的攻略,步骤如下: 步骤一:检查证书是否安装正确 在IIS服务器上,需要将证书正确地安装并且匹配相应的网站。所以,第一步是确保证书在服务器上正确地安装了,以及是否与网站匹配。如果证书未正确安装或匹配,将会出现调用证书异常的问题。你可以通过以下步骤来检查证书是否安装正确: 打开IIS …

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