.NET Core中的HttpClientFactory类用法详解

yizhihongxing

.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#操作SQLite数据库帮助类详解

    C#操作SQLite数据库帮助类详解 什么是SQLite数据库? SQLite是一种轻量级的关系型数据库管理系统,因其跨平台、易操作、高效等特点广受欢迎,可用于很多不同的应用场景。 C#如何操作SQLite数据库? C#作为一种高效的编程语言,内置了SQLite.NET库,可以直接通过System.Data.SQLite命名空间中的类进行对SQLite数据库…

    C# 2023年5月31日
    00
  • C#中的协变与逆变小结

    下面是“C#中的协变与逆变小结”的完整攻略: 什么是协变和逆变 协变和逆变是C#中的两个概念,它们都涉及到了类型转换。简单来说: 协变:表示在类型转换过程中,类型参数可以“向上转”,也就是说如果T1是T2的子类型,那么Func<T1>可以转换为Func<T2>。 逆变:表示在类型转换过程中,类型参数可以“向下转”,也就是说如果T1是T…

    C# 2023年5月14日
    00
  • 无法从 int? 转换为 int 运行时出现错误

    问题分析 在程序中常常会使用到可空类型(Nullable Type),可空类型表示能存储特定值类型(如 int、float)或者 null 值。在使用可空类型时,我们需要注意到数据类型转换的问题。例如,当我们把一个可空类型的 int? 变量赋值给 int 类型的变量时,就需要进行数据类型转换。如果该 int? 变量的值为 null,就会在进行转换时出现运行时…

    C# 2023年5月15日
    00
  • ASP.Net前台调用后台变量的方法

    要在 ASP.Net 前台页面中调用后台的变量,可以通过以下方法实现: 在后台代码中定义变量并使用public或protected关键字进行修饰。例如: //定义变量 protected string MyVariable; //给变量赋值 MyVariable = "Hello, World!"; 在前台页面中使用“<%=” 闭合…

    C# 2023年6月7日
    00
  • Microsoft .Net Remoting系列教程之一:.Net Remoting基础篇

    Microsoft.NetRemoting系列教程之一:.NetRemoting基础篇 .NetRemoting是一种用于实现分布式应用程序的技术。本教程将提供.NetRemoting基础知识的完整攻略,包括如何创建.NetRemoting应用程序、如何定义远程对象、如何使用远程对象以及两个示例。 创建.NetRemoting应用程序 要创建.NetRemo…

    C# 2023年5月15日
    00
  • C#开发的人脸左右相似度计算软件源码分析

    介绍C#开发的人脸左右相似度计算软件 “C#开发的人脸左右相似度计算软件”是一种基于C#语言编写的人脸图像处理工具,可以对输入的人脸图像进行左右对称处理,并计算出左右两侧差异的相似度值。该软件集成OpenCV人脸识别库和C#图形用户界面,可以方便地进行人脸相似度计算和可视化展示。 解析源码 该软件主要包括以下几个模块: 图像加载与处理:使用OpenCV库加载…

    C# 2023年6月7日
    00
  • Unity实现俄罗斯方块(二)

    Unity实现俄罗斯方块(二)攻略 1. 前言 在上一篇文章《Unity实现俄罗斯方块(一)》中,我们实现了俄罗斯方块游戏的基本框架,包括生成指定形状的方块、方块下落、方块旋转、消行等基本功能。接下来,我们在这个基础上,继续实现俄罗斯方块游戏的其他功能,包括左右移动和加速下落。 下面,我们就一步一步来详细讲解如何实现这些功能。 2. 左右移动 在俄罗斯方块游…

    C# 2023年6月1日
    00
  • 聊一聊C# 8.0中的await foreach使用

    下面是“聊一聊C#8.0中的await foreach使用”的完整攻略: 什么是await foreach 在C# 8.0中,可以使用异步枚举器(async iterator)和await foreach语法来迭代异步可枚举器(async enumerable)。await foreach把foreach循环与异步编程相结合,可以更简单、更有效地处理异步枚举…

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