起因 :由於需要前段時間寫了一個http請求的公共方法 使用的 HttpClient,但是在jmeter測試下 爆發了這個問題:“Cannot assign requested address Cannot assign requested address”;百度了一翻,基本都是說的端口占用完,也有很多解決方案,其中就找到了IHttpClientFactory這個解決方案,同時也拋棄之前的HttpClient用法,至於HttpClient和IHttpClientFactory的區別就不在記錄了,網上很多,最大區別就是IHttpClientFactory解決釋放問題開發不需要關心到的問題,用這個組件的原因也是因為目前項目也是使用的.net core ,就剛好集成進去。
但是在查詢IHttpClientFactory使用時,遇到些問題,查詢時,發現基本都是在官網復制下來的,但是我復制下來也用不了,因為基礎差也是百度了很久終於理出來了,在此記錄下來,如有大神路過還望指點一下,代碼可以直接復制使用,調用時注入服務即可
/// <summary> /// http 請求服務 /// </summary> public interface IHttpClientHelper: IApplicationService { /// <summary> /// 使用post返回異步請求直接返回對象 /// </summary> /// <typeparam name="T">返回對象類型</typeparam> /// <typeparam name="T2">請求對象類型</typeparam> /// <param name="url">請求鏈接</param> /// <param name="obj">請求對象數據</param> /// <param name="header">請求頭</param> /// <param name="postFrom">表單提交 注* postFrom不為null 代表表單提交, 為null標識驚悚格式請求</param> /// <param name="gzip">是否壓縮</param> /// <returns>請求返回的目標對象</returns> Task<T> PostObjectAsync<T, T2>(string url, T2 obj, Dictionary<string, string> header = null, Dictionary<string, string> postFrom = null, bool gzip = false); /// <summary> /// 使用Get返回異步請求直接返回對象 /// </summary> /// <typeparam name="T">請求對象類型</typeparam> /// <param name="url">請求鏈接</param> /// <returns>返回請求的對象</returns> Task<T> GetObjectAsync<T>(string url); }
/// <summary> /// http 請求服務 /// </summary> public class HttpClientHelper : ApplicationService, IHttpClientHelper { private readonly IHttpClientFactory _httpClientFactory; /// <summary> /// 構造函數 /// </summary> /// <param name="httpClientFactory"></param> public HttpClientHelper(IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; } #region http 請求方式 /// <summary> /// 使用post方法異步請求 /// </summary> /// <param name="url">目標鏈接</param> /// <param name="posData">發送的參數JSON字符串</param> /// <param name="header">請求頭</param> /// <param name="posFrom">表單提交格式</param> /// <param name="gzip">是否壓縮</param> /// <returns>返回的字符串</returns> public async Task<string> PostAsync(string url, string posData, Dictionary<string, string> header = null, Dictionary<string, string> posFrom = null,bool gzip = false) { //從工廠獲取請求對象 var client = _httpClientFactory.CreateClient(); //消息狀態 string responseBody = string.Empty; //存在則是表單提交信息 if (posFrom != null) { var formData = new MultipartFormDataContent(); foreach (var item in posFrom) { formData.Add(new StringContent(item.Value), item.Key); } //提交信息 var result = await client.PostAsync(url, formData); //獲取消息狀態 responseBody = await result.EnsureSuccessStatusCode().Content.ReadAsStringAsync(); } else {//json HttpContent content = new StringContent(posData); if (header != null) { client.DefaultRequestHeaders.Clear(); foreach (var item in header) { client.DefaultRequestHeaders.Add(item.Key, item.Value); } } content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); HttpResponseMessage response = await client.PostAsync(url, content); response.EnsureSuccessStatusCode(); if (gzip) { GZipInputStream inputStream = new GZipInputStream(await response.Content.ReadAsStreamAsync()); responseBody = new StreamReader(inputStream).ReadToEnd(); } else { responseBody = await response.Content.ReadAsStringAsync(); } } return responseBody; } /// <summary> /// 使用get方法異步請求 /// </summary> /// <param name="url">目標鏈接</param> /// <param name="header"></param> /// <param name="Gzip"></param> /// <returns>返回的字符串</returns> public async Task<string> GetAsync(string url, Dictionary<string, string> header = null, bool Gzip = false) { var client = _httpClientFactory.CreateClient(); //HttpClient client = new HttpClient(new HttpClientHandler() { UseCookies = false }); if (header != null) { client.DefaultRequestHeaders.Clear(); foreach (var item in header) { client.DefaultRequestHeaders.Add(item.Key, item.Value); } } HttpResponseMessage response = await client.GetAsync(url); response.EnsureSuccessStatusCode();//用來拋異常 string responseBody = ""; if (Gzip) { GZipInputStream inputStream = new GZipInputStream(await response.Content.ReadAsStreamAsync()); responseBody = new StreamReader(inputStream).ReadToEnd(); } else { responseBody = await response.Content.ReadAsStringAsync(); } return responseBody; } /// <summary> /// 使用post返回異步請求直接返回對象 /// </summary> /// <typeparam name="T">返回對象類型</typeparam> /// <typeparam name="T2">請求對象類型</typeparam> /// <param name="url">請求鏈接</param> /// <param name="obj">請求對象數據</param> /// <param name="header">請求頭</param> /// <param name="postFrom">表單提交 表單提交 注* postFrom不為null 代表表單提交, 為null標識驚悚格式請求</param> /// <param name="gzip">是否壓縮</param> /// <returns>請求返回的目標對象</returns> public async Task<T> PostObjectAsync<T, T2>(string url, T2 obj,Dictionary<string, string> header = null, Dictionary<string, string> postFrom = null, bool gzip = false) { String json = JsonConvert.SerializeObject(obj); string responseBody = await PostAsync(url, json, header, postFrom, gzip); //請求當前賬戶的信息 return JsonConvert.DeserializeObject<T>(responseBody);//把收到的字符串序列化 } /// <summary> /// 使用Get返回異步請求直接返回對象 /// </summary> /// <typeparam name="T">請求對象類型</typeparam> /// <param name="url">請求鏈接</param> /// <returns>返回請求的對象</returns> public async Task<T> GetObjectAsync<T>(string url) { string responseBody = await GetAsync(url); //請求當前賬戶的信息 return JsonConvert.DeserializeObject<T>(responseBody);//把收到的字符串序列化 } #endregion }
注* 我這里項目版本是.net core 2.2 在添加 IHttpClientFactory nueget包時根據自身版本號添加 大於.net 2.2 的可忽略 此外:
1.使用前需要在 Startup.cs 類 注入
//默認生命周期為2分鍾,可以使用此方法+配置 修改默認時間 SetHandlerLifetime(TimeSpan.FromMinutes(X));
services.AddHttpClient(); 具體介紹到官網查閱,