zoukankan      html  css  js  c++  java
  • .NetCore简单封装基于IHttpClientFactory的HttpClient请求

    .NetCore简单封装基于IHttpClientFactory的HttpClient请求

    IHttpClientFactory是什么?为什么出现了IHttpClientFactory

    一、IHttpClientFactory是什么?

    IHttpClientFactory是.netcore2.1才开始引入的,是HttpClient的工厂接口,它为我们提供了获取HttpClient的接口,它帮助我们维护HttpClient的生命周期。当我们需要HttpClient访问网络时,它会自动帮我们获取或者是创建HttpClient(存在空闲的HttpClient时,直接提供;当不存在可用的HttpClient时自动创建)。它相当于HttpClient池。

    二、为什么出现IHttpClientFactory?

    传统的HttpClient创建后,其占用了Socket资源并且其不会是及时的回收。我们每次new一个HttpClient时是一个全新的对象,所以在高并发下又是会导致socket资源耗尽(Unable to connect to the remote serverSystem.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted.)。而如果采用单例或者静态的HttpClient,却达不到高效的使用网络请求,而且当访问不同的url时,单例或者静态的HttpClient往往会导致访问混乱而出现错误。

    .NetCore简单封装基于IHttpClientFactory的HttpClient请求

    复制代码
      1  public class HttpWebClient
      2     {
      3 
      4         private IHttpClientFactory _httpClientFactory;
      5         private readonly ILogger<HttpWebClient> _logger;
      6         public HttpWebClient(IHttpClientFactory httpClientFactory, ILogger<HttpWebClient> logger)
      7         {
      8             this._httpClientFactory = httpClientFactory;
      9             this._logger = logger;
     10         }
     11 
     12         /// <summary>
     13         /// Get
     14         /// </summary>
     15         /// <param name="url"></param>
     16         /// <param name="dicHeaders"></param>
     17         /// <param name="timeoutSecond"></param>
     18         /// <returns></returns>
     19         public async Task<T> GetAsync<T>(string url, Dictionary<string, string> dicHeaders, int timeoutSecond = 180)
     20         {
     21             try
     22             {
     23                 var client = BuildHttpClient(dicHeaders, timeoutSecond);
     24                 var response = await client.GetAsync(url);
     25                 var responseContent = await response.Content.ReadAsStringAsync();
     26                 if (response.IsSuccessStatusCode)
     27                 {
     28                     return JsonUtil.Deserialize<T>(responseContent);
     29                 }
     30                 else
     31                 {
     32                     throw new CustomerHttpException(response.StatusCode.ToString(), responseContent);
     33                 }
     34             }
     35             catch (Exception ex)
     36             {
     37                 _logger.LogError($"HttpGet:{url} Error:{ex.ToString()}");
     38                 throw new Exception($"HttpGet:{url} Error", ex);
     39             }
     40         }
     41         /// <summary>
     42         /// Post
     43         /// </summary>
     44         /// <param name="url"></param>
     45         /// <param name="requestBody"></param>
     46         /// <param name="dicHeaders"></param>
     47         /// <param name="timeoutSecond"></param>
     48         /// <returns></returns>
     49         public async Task<T> PostAsync<T>(string url, string requestBody, Dictionary<string, string> dicHeaders, int timeoutSecond = 180)
     50         {
     51             try
     52             {
     53                 var client = BuildHttpClient(null, timeoutSecond);
     54                 var requestContent = GenerateStringContent(requestBody, dicHeaders);
     55                 var response = await client.PostAsync(url, requestContent);
     56                 var responseContent = await response.Content.ReadAsStringAsync();
     57                 if (response.IsSuccessStatusCode)
     58                 {
     59                     var result = JsonUtil.Deserialize<T>(responseContent);
     60                     return result;
     61                 }
     62                 else
     63                 {
     64                     throw new CustomerHttpException(response.StatusCode.ToString(), responseContent);
     65                 }
     66             }
     67             catch (Exception ex)
     68             {
     69                 _logger.LogError($"HttpPost:{url},body:{requestBody} Error:{ex.ToString()}");
     70                 throw new Exception($"HttpPost:{url} Error", ex);
     71             }
     72         }
     73         /// <summary>
     74         /// Put
     75         /// </summary>
     76         /// <param name="url"></param>
     77         /// <param name="requestBody"></param>
     78         /// <param name="dicHeaders"></param>
     79         /// <param name="timeoutSecond"></param>
     80         /// <returns></returns>
     81         public async Task<T> PutAsync<T>(string url, string requestBody, Dictionary<string, string> dicHeaders, int timeoutSecond = 180)
     82         {
     83             try
     84             {
     85                 var client = BuildHttpClient(null, timeoutSecond);
     86                 var requestContent = GenerateStringContent(requestBody, dicHeaders);
     87                 var response = await client.PutAsync(url, requestContent);
     88                 var responseContent = await response.Content.ReadAsStringAsync();
     89                 if (response.IsSuccessStatusCode)
     90                 {
     91                     var result = JsonUtil.Deserialize<T>(responseContent);
     92                     return result;
     93                 }
     94                 else
     95                 {
     96                     throw new CustomerHttpException(response.StatusCode.ToString(), responseContent);
     97                 }
     98             }
     99             catch (Exception ex)
    100             {
    101                 _logger.LogError($"HttpPut:{url},Body:{requestBody},  Error:{ex.ToString()}");
    102                 throw new Exception($"HttpPut:{url} Error", ex);
    103             }
    104         }
    105 
    106         /// <summary>
    107         /// Patch
    108         /// </summary>
    109         /// <param name="url"></param>
    110         /// <param name="requestString"></param>
    111         /// <param name="dicHeaders"></param>
    112         /// <param name="timeoutSecond"></param>
    113         /// <returns></returns>
    114         public async Task<T> PatchAsync<T>(string url, string requestBody, Dictionary<string, string> dicHeaders, int timeoutSecond = 180)
    115         {
    116             try
    117             {
    118                 var client = BuildHttpClient(null, timeoutSecond);
    119                 var requestContent = GenerateStringContent(requestBody, dicHeaders);
    120                 var response = await client.PatchAsync(url, requestContent);
    121                 var responseContent = await response.Content.ReadAsStringAsync();
    122                 if (response.IsSuccessStatusCode)
    123                 {
    124                     var result = JsonUtil.Deserialize<T>(responseContent);
    125                     return result;
    126                 }
    127                 else
    128                 {
    129                     throw new CustomerHttpException(response.StatusCode.ToString(), responseContent);
    130                 }
    131             }
    132             catch (Exception ex)
    133             {
    134                 _logger.LogError($"HttpPatch:{url},body:{requestBody}, Error:{ex.ToString()}");
    135                 throw new Exception($"HttpPatch:{url} Error", ex);
    136             }
    137         }
    138         /// <summary>
    139         /// Delete
    140         /// </summary>
    141         /// <param name="url"></param>
    142         /// <param name="dicHeaders"></param>
    143         /// <param name="timeoutSecond"></param>
    144         /// <returns></returns>
    145         public async Task<T> DeleteAsync<T>(string url, Dictionary<string, string> dicHeaders, int timeoutSecond = 180)
    146         {
    147             try
    148             {
    149                 var client = BuildHttpClient(dicHeaders, timeoutSecond);
    150                 var response = await client.DeleteAsync(url);
    151                 var responseContent = await response.Content.ReadAsStringAsync();
    152                 if (response.IsSuccessStatusCode)
    153                 {
    154                     var result = JsonUtil.Deserialize<T>(responseContent);
    155                     return result;
    156                 }
    157                 else
    158                 {
    159                     throw new CustomerHttpException(response.StatusCode.ToString(), responseContent);
    160                 }
    161             }
    162             catch (Exception ex)
    163             {
    164                 _logger.LogError($"HttpDelete:{url}, Error:{ex.ToString()}");
    165                 throw new Exception($"HttpDelete:{url} Error", ex);
    166             }
    167         }
    168         /// <summary>
    169         /// common request
    170         /// </summary>
    171         /// <param name="url"></param>
    172         /// <param name="method"></param>
    173         /// <param name="requestBody"></param>
    174         /// <param name="dicHeaders"></param>
    175         /// <param name="timeoutSecond"></param>
    176         /// <returns></returns>
    177         public async Task<T> ExecuteAsync<T>(string url, HttpMethod method, string requestBody, Dictionary<string, string> dicHeaders, int timeoutSecond = 180)
    178         {
    179             try
    180             {
    181                 var client = BuildHttpClient(null, timeoutSecond);
    182                 var request = GenerateHttpRequestMessage(url, requestBody, method, dicHeaders);
    183                 var response = await client.SendAsync(request);
    184                 var responseContent = await response.Content.ReadAsStringAsync();
    185                 if (response.IsSuccessStatusCode)
    186                 {
    187                     var result = JsonUtil.Deserialize<T>(responseContent);
    188                     return result;
    189                 }
    190                 else
    191                 {
    192                     throw new CustomerHttpException(response.StatusCode.ToString(), responseContent);
    193                 }
    194             }
    195             catch (Exception ex)
    196             {
    197                 _logger.LogError($"{method.ToString()}:{url},body:{requestBody}, Error:{ex.ToString()}");
    198                 throw new Exception($"{method.ToString()}:{url} Error", ex);
    199             }
    200 
    201         }
    202         /// <summary>
    203         /// Build HttpClient
    204         /// </summary>
    205         /// <param name="timeoutSecond"></param>
    206         /// <returns></returns>
    207         private HttpClient BuildHttpClient(Dictionary<string, string> dicDefaultHeaders, int? timeoutSecond)
    208         {
    209             var httpClient = _httpClientFactory.CreateClient();
    210             httpClient.DefaultRequestHeaders.Clear();   //in order that the client is not affected by the last request,it need to clear DefaultRequestHeaders
    211             httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    212             if (dicDefaultHeaders != null)
    213             {
    214                 foreach (var headerItem in dicDefaultHeaders)
    215                 {
    216                     if (!httpClient.DefaultRequestHeaders.Contains(headerItem.Key))
    217                     {
    218                         httpClient.DefaultRequestHeaders.Add(headerItem.Key, headerItem.Value);
    219                     }
    220                 }
    221             }
    222             if (timeoutSecond != (int?)null)
    223             {
    224                 httpClient.Timeout = TimeSpan.FromSeconds(timeoutSecond.Value);
    225             }
    226             return httpClient;
    227         }
    228 
    229         /// <summary>
    230         /// Generate HttpRequestMessage
    231         /// </summary>
    232         /// <param name="url"></param>
    233         /// <param name="requestBody"></param>
    234         /// <param name="method"></param>
    235         /// <param name="dicHeaders"></param>
    236         /// <returns></returns>
    237         private HttpRequestMessage GenerateHttpRequestMessage(string url, string requestBody, HttpMethod method, Dictionary<string, string> dicHeaders)
    238         {
    239             var request = new HttpRequestMessage(method, url);
    240             if (!string.IsNullOrEmpty(requestBody))
    241             {
    242                 request.Content = new StringContent(requestBody);
    243             }
    244             if (dicHeaders != null)
    245             {
    246                 foreach (var header in dicHeaders)
    247                 {
    248                     request.Headers.Add(header.Key, header.Value);
    249                 }
    250             }
    251             return request;
    252         }
    253         /// <summary>
    254         ///  Generate StringContent
    255         /// </summary>
    256         /// <param name="requestBody"></param>
    257         /// <param name="dicHeaders"></param>
    258         /// <returns></returns>
    259         private StringContent GenerateStringContent(string requestBody, Dictionary<string, string> dicHeaders)
    260         {
    261             var content = new StringContent(requestBody);
    262             if (dicHeaders != null)
    263             {
    264                 foreach (var headerItem in dicHeaders)
    265                 {
    266                     content.Headers.Add(headerItem.Key, headerItem.Value);
    267                 }
    268             }
    269             return content;
    270         }
    271 
    272 
    273     }
    复制代码
    CustomerHttpException类的简单定义
    复制代码
     1     public class CustomerHttpException : Exception
     2     {
     3         public string ErrorCode { get; set; }
     4         public string ErrorMessage { get; set; }
     5         public CustomerHttpException() : base()
     6         { }
     7         public CustomerHttpException(string errorCode, string errorMessage) : base()
     8         {
     9             this.ErrorCode = errorCode;
    10             this.ErrorMessage = ErrorMessage;
    11         }
    12     }
    复制代码

    以上是简单的Http请求封装。其中一些值得注意的点

    1、创建的HttpClient是由HttpClientFactory统一管理的,所以当指定了DefaultRequestHeaders时,下次再次从HttpClientFactory中获取时可能带着上次的Header信息。所以需要对其进行Clear。

    2、封装了统一的调用接口ExecuteAsync,建议采用该接口进行http请求,此时就不会去配置DefaultRequestHeaders,而是将Header信息配置在请求信息中。

    3、自定义了CustomerHttpException,主要是为了支持ResultFul风格的api。通过外层捕获CustomerHttpException,从而解析出具体的错误信息。

  • 相关阅读:
    的地方d'fe'w
    日期
    equals方法
    接口作为成员变量类型
    匿名内部类注意事项
    匿名内部类
    局部内部类注意问题
    可以
    C中的volatile关键字
    继承权限问题
  • 原文地址:https://www.cnblogs.com/yidanda888/p/15561382.html
Copyright © 2011-2022 走看看