利用IHttpClientFactory能夠無縫建立HttpClient實例,避免手動管理它們的生命週期。html
當使用ASP.Net Core開發應用程序時,可能常常須要經過HttpClient調用WebAPI的方法以檢查終結點是否正常工做。要實現這一點,一般須要實例化HttpClient並使用該實例來調用你的方法。可是直接使用HttpClient也有一些缺點,主要與手動管理實例的生命週期有關。git
你可使用IHttpClientFactory建立HttpClient來避免這些問題。IHttpClientFactory是在.Net Core 2.1引入的,它提供了一個命名,配置和建立HttpClient實例的核心功能,並能自動管理實例的池化和生命週期。github
下面咱們經過代碼進一步討論HttpClient和IHttpClientFactory,以及所設計的概念。要使用提供的代碼,你須要安裝Visual Studio 2019。json
在Visual Studio 2019中建立一個ASP.NET Core MVC項目 api
假設你的系統中安裝了Visual Studio 2019,請按照下面列出來的步驟建立一個新的ASP.NET Core項目。緩存
1. 啓動Visual Studio IDE。app
2. 點擊「建立新項目」。asp.net
3. 在「建立新項目」窗口中,從模板列表中選擇ASP.NET Core Web應用程序。socket
4. 單擊Next。async
5. 在「配置新項目」窗口中,指定新項目的名稱和位置。
6. 能夠選擇「將解決方案和項目放在同一個目錄中」複選框。
7. 點擊Create。
8. 在「建立一個新的ASP.NET Core Web應用程序「窗口中,選擇。NET Core做爲運行時,而後選擇asp.net Core做爲運行時。NET Core 3.1(或更高版本)。
9. 選擇「Web Application (Model-View-Controller)」做爲項目模板來建立一個新的ASP.NET Core MVC應用程序。
10. 確保複選框「啓用Docker支持」和「配置HTTPS」沒有選中,由於咱們不會在這裏使用這些特性。
11. 確保身份驗證設置爲「無身份驗證」,由於咱們也不會使用身份驗證。
12. 單擊Create。
按照這些步驟將建立一個新的ASP.NET Core MVC應用程序。在新項目中,建立一個新的API Controller,並使用默認名稱保存它,即ValuesController。咱們將在接下來的部分中使用這個項目。
挑戰HttpClient
儘管HttpClient沒有直接實現IDisposable接口,但它擴展了System.Net.Http。HttpMessageInvoker,這個類實現了IDisposable。然而,當使用HttpClient實例時,你不該該手動操做釋放它們。儘管能夠在HttpClient實例上調用Dispose方法,但不推薦這樣作。
應該怎麼作呢?一種選擇是使HttpClient靜態化,或者將HttpClient的非靜態實例包裝在自定義類中,並使其成爲單例類。可是更好的替代方法是使用IHttpClientFactory來生成HttpClient的實例,而後使用該實例來調用操做方法。
IHttpClientFactory 和HttpClientFactory
IHttpClientFactory是一個由DefaultHttpClientFactory類實現的接口,這是一個工廠模式。DefaultHttpClientFactory實現了IHttpClientFactory和IHttpMessageHandlerFactory接口。IHttpClientFactory提供了ASP.NET Core對建立、緩存和處理HttpClient實例提供了出色的內置支持。
請注意,HttpClientFactory只是一個幫助類,用於建立使用提供的處理程序配置的HttpClient實例。這個類有如下方法:
Create(DelegatingHandler[])
Create(HttpMessageHandler,DelegatingHandler[])
CreatePipeline(HttpMessageHandler,IEnumerable<DelegatingHandler>)
重載的HttpClientFactory類的Create方法看起來像這樣:
public static HttpClient Create(params DelegatingHandler[] handlers) { return Create(new HttpClientHandler(), handlers); } public static HttpClient Create(HttpMessageHandler innerHandler, params DelegatingHandler[] handlers) { HttpMessageHandler pipeline = CreatePipeline(innerHandler, handlers); return new HttpClient(pipeline); }
引入HttpClientFactory和IHttpClientFactory是爲了更好地管理HttpMessageHandler實例的生命週期。
爲何使用IHttpClientFactory?
當你釋放HttpClient實例時,鏈接將保持打開狀態長達4分鐘。此外,能夠在任什麼時候間點打開socket的數量是有限制的——不能同時打開太多socket。所以,當使用太多HttpClient實例時,可能會耗盡socket。
這就是IHttpClientFactory的意義所在。你能夠經過利用IHttpClientFactory來建立用於調用HTTP API方法的HttpClient實例,以免HttpClient所面臨的問題。在ASP.NET Core中實現IHttpClientFactory的主要目標是爲了確保使用工廠模式建立HttpClient實例的同時避免socket耗盡。
在ASP.NET Core中註冊IHttpClientFactory實例
你能夠在Startup類的ConfigureServices方法中,經過調用IServiceCollection實例上的AddHttpClient擴展方法註冊一個IHttpClientFactory類型的實例,以下:
public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); services.AddHttpClient(); }
將IHttpClientFactory實例注入到控制器
能夠經過以下代碼將將IHttpClientFactory實例注入到控制器:
public class HomeController : Controller { private IHttpClientFactory _httpClientFactory; private readonly ILogger<HomeController> _logger; public HomeController(ILogger<HomeController> logger, IHttpClientFactory httpClientFactory) { _logger = logger; _httpClientFactory = httpClientFactory; } }
在Action中調用HttpClient
要經過使用IHttpClientFactory建立HttpClient,應該調用CreateClient方法。一旦HttpClient實例可用,就能夠在HomeController類的index方法中使用如下代碼來調用ValuesController類的Get方法。
public async Task<IActionResult> Index() { HttpClient httpClient = _httpClientFactory.CreateClient(); httpClient.BaseAddress = new Uri("http://localhost:1810/"); var response = await httpClient.GetAsync("/api/values"); string str = await response.Content.ReadAsStringAsync(); List<string> data = JsonSerializer.Deserialize<List<string>>(str); return View(data); }
使用IHttpClientFactory在ASP.NET Core中建立和管理HttpClient實例
有幾種方法能夠在應用程序中使用IHttpClientFactory。這包括直接使用IHttpClientFactory、使用命名client和類型client。
基本的或通常的使用模式,即直接使用IHttpClientFactory—在前面的小節中已經討論過了。請參考「註冊一個IHttpClientFactory實例」一節,該節討論瞭如何註冊HttpClient實例。
若是你想使用不一樣配置的HttpClient實例,如下是一個不錯的選擇。下面的代碼片斷說明了如何建立。
services.AddHttpClient("github", c => { c.BaseAddress = new Uri("https://api.github.com/"); c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json"); c.DefaultRequestHeaders.Add("User-Agent", "This is a test user agent"); });
第二種方法是使用包裝了HttpClient實例的自定義類,該自定義類封裝了經過HTTP協議調用全部終結點的邏輯。下面的代碼片斷說明了如何定義自定義HttpClient類。
public class ProductService : IProductService { private IHttpClientFactory _httpClientFactory; private readonly HttpClient _httpClient; private readonly string _baseUrl = "http://localhost:1810/"; public ProductService(HttpClient httpClient) { _httpClient = httpClient; } public async Task<Catalog> GetAllProducts() { _httpClient = _httpClientFactory.CreateClient(); _httpClient.BaseAddress = new Uri(_baseUrl); var uri = "/api/products"; var result = await _httpClient.GetStringAsync(uri); return JsonConvert.DeserializeObject<Product>(result); } }
經過如下代碼註冊自定義的client:
services.AddHttpClient<IProductService, ProductService>();
將MessageHandler添加到命名管道中
MessageHandler是擴展自HttpMessageHandler類,它能夠接受HTTP請求並返回HTTP響應。若是你想構建本身的MessageHandler,你應該建立一個繼承DelegatingHandler的類。
你能夠將HttpMessageHandler添加到請求處理管道中。能夠在Startup類的ConfigureServices方法中使用如下代碼將HttpMessageHandler添加到管道中。
public void ConfigureServices(IServiceCollection services) { services.AddHttpClient("github", c => { c.BaseAddress = new Uri("https://api.github.com/"); }) .AddHttpMessageHandler<DemoHandler>(); services.AddTransient<DemoHandler>(); }
IHttpClientFactory是一個自.net Core 2.1以來就可用的工廠類。若是你使用IHttpClientFactory來建立HttpClient實例,那麼底層HttpClientMessagehandler實例的池化和生命週期將自動管理。IHttpClientFactory還負責處理一些常見問題,好比日誌記錄。
原文連接:https://www.infoworld.com/article/3586176/how-to-use-ihttpclientfactory-in-aspnet-core.html