前言
為了更方便在服務端調用 HTTP 請求,微軟在 .NET Framework 4.x 的時候引入了 HttpClient。但 HttpClient 有很多嚴重問題,一直飽受詬病,比如 InfoQ 的這篇文章 t.cn/Evzy80y,吐槽了 HttpClient 不能立即關閉連接、性能消耗嚴重等的問題。
Http協議的重要性相信不用我多說了,HttpClient相比傳統JDK自帶的URLConnection,增加了易用性和靈活性,它不僅是客戶端發送Http請求變得容易,而且也方便了開發人員測試接口(基于Http協議的),即提高了開發的效率,也方便提高代碼的健壯性。因此熟練掌握HttpClient是很重要的必修內容,掌握HttpClient后,相信對于Http協議的了解會更加深入。
.NET Core 2.1 開始引入的 HttpClientFactory 解決了 HttpClient 的所有痛點。有了 HttpClientFactory,我們不需要關心如何創建 HttpClient,又如何釋放它。通過它可以創建具有特定業務的 HttpClient,而且可以很友好的和 DI 容器結合使用,更為靈活。
下面以 ASP.NET Core 為例介紹 HttpClient 新的三種正確使用方式。
一、直接使用方式
不管是哪種方式,都要先注冊服務,對于 ASP.NET Core 應用則是在 Startup.cs 文件的 ConfigureServices 添加如果代碼:
1
|
services.AddHttpClient(); |
然后在 Controller 中通過構造注入的試獲得 IHttpClientFactory,然后通過它來創建 HttpClient 對象。示例代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public class ValuesController : BaseController { private readonly IHttpClientFactory _httpClientFactory; public ValuesController(IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; } [HttpGet] public async Task<ActionResult> Get() { var client = _httpClientFactory.CreateClient(); string result = await client.GetStringAsync( "/" ); return Ok(result); } } |
這種使用方式適合一次性的 HTTP 請求調用,弊端是如果多次都要請求 github 的接口,那就得寫很多重復代碼配置 HttpClient。
二、命名式使用方式
命名式的使用方式可以解決第一種方式的問題,對于特定域名的 HTTP 調用,可以只做一次配置,然后在多個地方通過名稱拿到相同的 Client 來使用。
首先在 Startup.cs 注冊服務的地方添加帶有特定名稱的 HttpClient 服務,并添加需要的配置,如下示例:
1
2
3
4
5
6
7
|
services.AddHttpClient(); services.AddHttpClient( "github" , c => { c.DefaultRequestHeaders.Add( "Accept" , "application/vnd.github.v3+json" ); c.DefaultRequestHeaders.Add( "User-Agent" , "HttpClientFactory-Sample" ); }); |
注意這里添加了兩次 AddHttpClient,一次是沒有命名的,一次是有命名的。在 Controller 中的使用方式是:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public class ValuesController : BaseController { private readonly IHttpClientFactory _httpClientFactory; public ValuesController(IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; } [HttpGet] public async Task<ActionResult> Get() { var client = _httpClientFactory.CreateClient( "github" ); string result = await client.GetStringAsync( "/" ); return Ok(result); } } |
但如果使用很頻繁,這種獲取 Client 的方式還是有一點麻煩。下面介紹第三種方式,可以在使用的時候方便一點,但配置要麻煩些。
三、類型化使用方式
類型化的使用方式可以預先把配置放到自定義的 HttpClient 中,然后在需要的地方都過依賴注入直接拿到 HttpClient 實例。
我們來看具體的例子,首先自定義一個 HttClient 類,比如訪問 github 接口的類可以這樣定義:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public class GitHubClient { public HttpClient Client { get ; private set ; } public GitHubClient(HttpClient httpClient) { httpClient.DefaultRequestHeaders.Add( "Accept" , "application/vnd.github.v3+json" ); httpClient.DefaultRequestHeaders.Add( "User-Agent" , "HttpClientFactory-Sample" ); Client = httpClient; } public async Task< string > GetData() { return await _client.GetStringAsync( "/" ); } } |
這里的 GetData 就是額外擴展的共用方法。使用前需要為這個類注冊服務:
1
|
services.AddHttpClient<GitHubClient>(); |
然后在需要的地方(比如 Controller)中這樣使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public class ValuesController : BaseController { private readonly GitHubClient _gitHubClient;; public ValuesController(GitHubClient gitHubClient) { _gitHubClient = gitHubClient; } [HttpGet] public async Task<ActionResult> Get() { string result = await _gitHubClient.GetData(); return Ok(result); } } |
類型化的方式和命名式的方式相比,雖然在配置的時候會麻煩一點,但它有兩個好處:一是不用通過名稱字符串來獲得 Client,而是直接通過依賴注入獲得具體的 Client;二是可以在自定義的 HttpClient 類中擴展共用的方法。
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。
原文鏈接:https://www.cnblogs.com/willick/p/net-core-httpclient.html