1. 程式人生 > >NetCore下的HTTP請求IHttpClientFactory

NetCore下的HTTP請求IHttpClientFactory

使用方式

IHttpClientFactory有四種模式:

  • 基本用法
  • 命名客戶端
  • 型別化客戶端
  • 生成的客戶端

基本用法

在 Startup.ConfigureServices 方法中,通過在 IServiceCollection 上呼叫 AddHttpClient 擴充套件方法可以註冊 IHttpClientFactory

services.AddHttpClient();

註冊之後可以像依賴注入DI似得在類中通過建構函式注入形式使用,虛擬碼:

class A
{
    private readonly IHttpClientFactory _clientFactory;
    public A(IHttpClientFactory clientFactory)
    {
        _clientFactory = clientFactory;
    }
    
    Public void Use()
    {
         var request=new HttpRequestMessage(HttpMethod.Get,"www.baidu.com")   ;
         var client = _clientFactory.CreateClient();
         var response = await client.SendAsync(request); 
         if (response.IsSuccessStatusCode)
         {
            Branches = await response.Content.ReadAsAsync<IEnumerable<GitHubBranch>>();
         }
        else
        {
            GetBranchesError = true;
            Branches = Array.Empty<GitHubBranch>();
        }      
    }
}

命名客戶端

也是在基本用法的基礎上增加配置引數:例如增加一個baidu下的客戶端:

services.AddHttpClient("baidu",c=>
{
    c.BaseAddress = new Uri("https://api.baidu.com/");
    //其他一些引數
});

 

然後在使用的時候只是需要傳遞客戶端名稱就自動使用baidu這個地址的基礎地址配置:

 var client = _clientFactory.CreateClient("baidu");

型別化客戶端

說的明白一點就是在使用類的建構函式中可以直接接受HttpClient 型別,不用在使用IHttpClientFactory 介面的CreateClient方法建立,但是首要條件就是要先建立注入型別,然後在ConfigureServices 方法同時注入:

services.AddHttpClient<classHttp>();

注入型別:

public class classHttp
{
     public HttpClient Client { get; }
     public GitHubService(HttpClient client)
     {
           client.BaseAddress = new Uri("https://api.baidu.com/");
           //同ConfigureServices 中一樣設定一些其他引數
            Client = client;
     }
}

生成的客戶端

這個我個人理解為就是配置使用第三方庫,然後可以注入介面型別,介面中可以寫一些方法介面。然後通過介面類直接呼叫介面。

個人理解:就是類似於一個介面對映,地址對映似得。通過結合第三方庫(官方推薦Refit)實現請求一個地址別名的方式,別名就是指定義的介面。然後別名通過增加特性Get(“路徑”)或者post("路徑)的形式重新指向真實的請求介面地址。通過請求這個本地介面方法實現轉化請求的真實地址。

舉例定義介面:

public interface IHelloClient
{
    [Get("/MyInterFace")]
    Task<Reply> GetMessageAsync();
}

配置Refit外掛:

也是和正常配置類似,在後面增加介面的服務注入。

public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient("hello", c =>
    {
        c.BaseAddress = new Uri("http://localhost:5000");
    })
    .AddTypedClient(c => Refit.RestService.For<IHelloClient>(c));

    services.AddMvc();
}

然後再說介面上面的Get("/MyInterFace")方法;這個我們就不做另一個專案就在當前專案下,所以可以直接就在api專案下建立一個名為MyInterFace的方法。

[ApiController]
public class TestController : ControllerBase
{
     [HttpGet("/")]
    public async Task<sting> MyInterFace()
    {
        return "ceshi";
    }
}

然後就可以使用介面了:

[ApiController]
public class ValuesController : ControllerBase
{
    private readonly IHelloClient _client;

    public ValuesController(IHelloClient client)
    {
        _client = client;
    }

    [HttpGet("/")]
    public async Task<ActionResult<Reply>> Index()
    {
        return await _client.GetMessageAsync();
    }
}

在這了的_client.GetMessageAsync()方法就是呼叫了介面方法,看著是呼叫了GetMessageAsync方法其實是做了對映,對映地址就是上面特性寫的MyInterFace方法。通過斷點也可以驗證此結論。然後不同專案下也是同一個意思,假如我們請求百度的地址:www.baidu.com/api/b這個介面

我們在配置出把請求地址http://localhost:5000改為www.baidu.com/api,然後再把GetMessageAsync方法上面的MyInterFace改為b即可。

出站請求中介軟體

個人理解為請求返回前處理程式,就是繼承 DelegatingHandler派生類重寫SendAsync 方法。在將請求傳遞至管道中的下一個處理程式之前執行程式碼:

public class ValidateHeaderHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        if (!request.Headers.Contains("X-API-KEY"))
        {
            return new HttpResponseMessage(HttpStatusCode.BadRequest)
            {
                Content = new StringContent(
                    "You must supply an API key header called X-API-KEY")
            };
        }

        return await base.SendAsync(request, cancellationToken);
    }
}

然後在ConfigureServices中:

services.AddTransient<ValidateHeaderHandler>();//註冊處理程式
services.AddHttpClient("externalservice", c =>
{
    // Assume this is an "external" service which requires an API KEY
    c.BaseAddress = new Uri("https://localhost:5000/");
})
.AddHttpMessageHandler<ValidateHeaderHandler>();/注入到http請求管道

 

可以同時註冊多個處理程式。

HttpClient和生存週期

每次對 IHttpClientFactory 呼叫 CreateClient 都會返回一個新 HttpClient 例項。 每個命名的客戶端都具有一個 HttpMessageHandler。 工廠管理 HttpMessageHandler 例項的生存期。

 HttpClient例項不是與HttpMessageHandler一起銷燬的,HttpMessageHandler在池中生存,如果生命週期未到不會被銷燬,會被新的HttpClient 例項使用。

處理程式的預設生存週期是2分鐘,可以通過配置修改:

services.AddHttpClient("extendedhandlerlifetime")
    .SetHandlerLifetime(TimeSpan.FromMinutes(5));

 原文有道雲筆記連線:https://note.youdao.com/ynoteshare1/index.html?id=80912dd7064716428880a8e201b76a11&type=