zoukankan      html  css  js  c++  java
  • ASP.NET Core使用IHttpClientFactory发起HTTP请求

      在.NET项目开发中,我们常用于发起HTTP请求HttpClient类由于先天缺陷,调用HttpClient的Dispose方法后并不能立即释放套接字(Sokect)资源。

    在频繁的发起HTTP请求的系统中将会存在大量的处于TIME_WAIT状态的套接字资源,最终导致套接字资源被耗尽。为了解决这个问题,微软推出了IHttpClientFactory方案,大概意思就是将链接对象池化。、

    具体使用案列如下,(本案列只封装了部分参数,基本已经可以满足绝大部分的需求,如有特殊要求,请自行扩展参数。代码中使用了Newtonsoft.Json。

    1.在Startup中的ConfigureServices方法中注册IHttpClientFactory.和实现类 

    public void ConfigureServices(IServiceCollection services)
    {
       //注册IHttpClientFactory
       services.AddHttpClient();
       //注册IHttpClientFactory的实现到DI容器
       services.AddTransient<HttpClientHelper>();
    }

     2.基于IHttpClientFactory的Helper类封装。

    using System;
    using System.Collections.Generic;
    using System.Net.Http;
    using System.Threading.Tasks;
    using Newtonsoft.Json;
    
    namespace Research.Web.Common
    {
        /// <summary>
        /// HTTP帮助类
        /// </summary>
        public class HttpClientHelper
        {
            private IHttpClientFactory _httpClientFactory;
            public HttpClientHelper(IHttpClientFactory httpClientFactory)
            {
                _httpClientFactory = httpClientFactory;
            }
    
            /// <summary>
            /// 发起GET异步请求
            /// </summary>
            /// <typeparam name="T">返回类型</typeparam>
            /// <param name="url">请求地址</param>
            /// <param name="headers">请求头信息</param>
            /// <param name="timeOut">请求超时时间,单位秒</param>
            /// <returns>返回string</returns>
            public async Task<string> GetAsync(string url, Dictionary<string, string> headers = null, int timeOut = 30)
            {
                var hostName = GetHostName(url);
                using (HttpClient client = _httpClientFactory.CreateClient(hostName))
                {
                    client.Timeout = TimeSpan.FromSeconds(timeOut);
                    if (headers?.Count > 0)
                    {
                        foreach (string key in headers.Keys)
                        {
                            client.DefaultRequestHeaders.Add(key, headers[key]);
                        }
                    }
                    using (HttpResponseMessage response = await client.GetAsync(url))
                    {
                        if (response.IsSuccessStatusCode)
                        {
                            string responseString = await response.Content.ReadAsStringAsync();
                            return responseString;
                        }
                        else
                        {
                            return string.Empty;
                        }
                    }
                }
            }
    
    
            /// <summary>
            /// 发起POST异步请求
            /// </summary>
            /// <param name="url">请求地址</param>
            /// <param name="body">POST提交的内容</param>
            /// <param name="bodyMediaType">POST内容的媒体类型,如:application/xml、application/json</param>
            /// <param name="responseContentType">HTTP响应上的content-type内容头的值,如:application/xml、application/json、application/text、application/x-www-form-urlencoded等</param>
            /// <param name="headers">请求头信息</param>
            /// <param name="timeOut">请求超时时间,单位秒</param>
            /// <returns>返回string</returns>
            public async Task<string> PostAsync(string url, string body,
                string bodyMediaType = null,
                string responseContentType = null,
                Dictionary<string, string> headers = null,
                int timeOut = 30)
            {
                var hostName = GetHostName(url);
                using (HttpClient client = _httpClientFactory.CreateClient(hostName))
                {
                    client.Timeout = TimeSpan.FromSeconds(timeOut);
                    if (headers?.Count > 0)
                    {
                        foreach (string key in headers.Keys)
                        {
                            client.DefaultRequestHeaders.Add(key, headers[key]);
                        }
                    }
                    StringContent content = new StringContent(body, System.Text.Encoding.UTF8, mediaType: bodyMediaType);
                    if (!string.IsNullOrWhiteSpace(responseContentType))
                    {
                        content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse(responseContentType);
                    }
                    using (HttpResponseMessage response = await client.PostAsync(url, content))
                    {
                        if (response.IsSuccessStatusCode)
                        {
                            string responseString = await response.Content.ReadAsStringAsync();
                            return responseString;
                        }
                        else
                        {
                            return string.Empty;
                        }
                    }
                }
            }
    
            /// <summary>
            /// 发起POST异步请求
            /// </summary>
            /// <param name="url">请求地址</param>
            /// <param name="body">POST提交的内容</param>
            /// <param name="bodyMediaType">POST内容的媒体类型,如:application/xml、application/json</param>
            /// <param name="responseContentType">HTTP响应上的content-type内容头的值,如:application/xml、application/json、application/text、application/x-www-form-urlencoded等</param>
            /// <param name="headers">请求头信息</param>
            /// <param name="timeOut">请求超时时间,单位秒</param>
            /// <returns>返回string</returns>
            public async Task<string> PutAsync(string url, string body,
                string bodyMediaType = null,
                string responseContentType = null,
                Dictionary<string, string> headers = null,
                int timeOut = 30)
            {
                var hostName = GetHostName(url);
                using (HttpClient client = _httpClientFactory.CreateClient(hostName))
                {
                    client.Timeout = TimeSpan.FromSeconds(timeOut);
                    if (headers?.Count > 0)
                    {
                        foreach (string key in headers.Keys)
                        {
                            client.DefaultRequestHeaders.Add(key, headers[key]);
                        }
                    }
                    StringContent content = new StringContent(body, System.Text.Encoding.UTF8, mediaType: bodyMediaType);
                    if (!string.IsNullOrWhiteSpace(responseContentType))
                    {
                        content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse(responseContentType);
                    }
                    using (HttpResponseMessage response = await client.PutAsync(url, content))
                    {
                        if (response.IsSuccessStatusCode)
                        {
                            string responseString = await response.Content.ReadAsStringAsync();
                            return responseString;
                        }
                        else
                        {
                            return string.Empty;
                        }
                    }
                }
            }
    
            /// <summary>
            /// 发起GET异步请求
            /// </summary>
            /// <typeparam name="T">返回类型</typeparam>
            /// <param name="url">请求地址</param>
            /// <param name="headers">请求头信息</param>
            /// <param name="timeOut">请求超时时间,单位秒</param>
            /// <returns>返回string</returns>
            public async Task<string> DeleteAsync(string url, Dictionary<string, string> headers = null, int timeOut = 30)
            {
                var hostName = GetHostName(url);
                using (HttpClient client = _httpClientFactory.CreateClient(hostName))
                {
                    client.Timeout = TimeSpan.FromSeconds(timeOut);
                    if (headers?.Count > 0)
                    {
                        foreach (string key in headers.Keys)
                        {
                            client.DefaultRequestHeaders.Add(key, headers[key]);
                        }
                    }
                    using (HttpResponseMessage response = await client.DeleteAsync(url))
                    {
                        if (response.IsSuccessStatusCode)
                        {
                            string responseString = await response.Content.ReadAsStringAsync();
                            return responseString;
                        }
                        else
                        {
                            return string.Empty;
                        }
                    }
                }
            }
    
            /// <summary>
            /// 发起GET异步请求
            /// </summary>
            /// <typeparam name="T">返回类型</typeparam>
            /// <param name="url">请求地址</param>
            /// <param name="headers">请求头信息</param>
            /// <param name="timeOut">请求超时时间,单位秒</param>
            /// <returns>返回T</returns>
            public async Task<T> GetAsync<T>(string url, Dictionary<string, string> headers = null, int timeOut = 30) where T : new()
            {
                string responseString = await GetAsync(url, headers, timeOut);
                if (!string.IsNullOrWhiteSpace(responseString))
                {
                    return JsonConvert.DeserializeObject<T>(responseString);
                }
                else
                {
                    return default(T);
                }
            }
    
    
            /// <summary>
            /// 发起POST异步请求
            /// </summary>
            /// <typeparam name="T">返回类型</typeparam>
            /// <param name="url">请求地址</param>
            /// <param name="body">POST提交的内容</param>
            /// <param name="bodyMediaType">POST内容的媒体类型,如:application/xml、application/json</param>
            /// <param name="responseContentType">HTTP响应上的content-type内容头的值,如:application/xml、application/json、application/text、application/x-www-form-urlencoded等</param>
            /// <param name="headers">请求头信息</param>
            /// <param name="timeOut">请求超时时间,单位秒</param>
            /// <returns>返回T</returns>
            public async Task<T> PostAsync<T>(string url, string body,
                string bodyMediaType = null,
                string responseContentType = null,
                Dictionary<string, string> headers = null,
                int timeOut = 30) where T : new()
            {
                string responseString = await PostAsync(url, body, bodyMediaType, responseContentType, headers, timeOut);
                if (!string.IsNullOrWhiteSpace(responseString))
                {
                    return JsonConvert.DeserializeObject<T>(responseString);
                }
                else
                {
                    return default(T);
                }
            }
    
            /// <summary>
            /// 发起PUT异步请求
            /// </summary>
            /// <typeparam name="T">返回类型</typeparam>
            /// <param name="url">请求地址</param>
            /// <param name="body">POST提交的内容</param>
            /// <param name="bodyMediaType">POST内容的媒体类型,如:application/xml、application/json</param>
            /// <param name="responseContentType">HTTP响应上的content-type内容头的值,如:application/xml、application/json、application/text、application/x-www-form-urlencoded等</param>
            /// <param name="headers">请求头信息</param>
            /// <param name="timeOut">请求超时时间,单位秒</param>
            /// <returns>返回T</returns>
            public async Task<T> PutAsync<T>(string url, string body,
                string bodyMediaType = null,
                string responseContentType = null,
                Dictionary<string, string> headers = null,
                int timeOut = 30) where T : new()
            {
                string responseString = await PutAsync(url, body, bodyMediaType, responseContentType, headers, timeOut);
                if (!string.IsNullOrWhiteSpace(responseString))
                {
                    return JsonConvert.DeserializeObject<T>(responseString);
                }
                else
                {
                    return default(T);
                }
            }
    
            /// <summary>
            /// 发起DELETE异步请求
            /// </summary>
            /// <typeparam name="T">返回类型</typeparam>
            /// <param name="url">请求地址</param>
            /// <param name="headers">请求头信息</param>
            /// <param name="timeOut">请求超时时间,单位秒</param>
            /// <returns>返回T</returns>
            public async Task<T> DeleteAsync<T>(string url, Dictionary<string, string> headers = null, int timeOut = 30) where T : new()
            {
                string responseString = await DeleteAsync(url, headers, timeOut);
                if (!string.IsNullOrWhiteSpace(responseString))
                {
                    return JsonConvert.DeserializeObject<T>(responseString);
                }
                else
                {
                    return default(T);
                }
            }
            #region 私有函数
    
            /// <summary>
            /// 获取请求的主机名
            /// </summary>
            /// <param name="url"></param>
            /// <returns></returns>
            private static string GetHostName(string url)
            {
                if (!string.IsNullOrWhiteSpace(url))
                {
                    return url.Replace("https://", "").Replace("http://", "").Split('/')[0];
                }
                else
                {
                    return "AnyHost";
                }
            }
    
            #endregion
        }
    }

     3.调用基于IHttpClientFactory的Helper类发起Http请求。

    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Mvc;
    using Research.Web.Common;
    
    namespace Research.Web.Controllers
    {
        [ApiExplorerSettings(GroupName = "Web")]
        [ApiController]
        [Route("Web")]
        public class WebeController : ControllerBase
        {
            private HttpClientHelper _httpClientHelper;
    
            /// <summary>
            /// 从DI容器中获取HttpClientHelper实列对象
            /// </summary>
            /// <param name="httpClientHelper"></param>
            public WebeController(HttpClientHelper httpClientHelper)
            {
                this._httpClientHelper = httpClientHelper;
            }
    
            /// <summary>
            /// 测试异步HttpClient
            /// </summary>
            /// <returns></returns>
            [HttpGet("testhttpasync")]
            public async Task<JsonResult> TestAsyncHttpClientFactory()
            {
                var model = await _httpClientHelper.GetAsync<ResponseModel>("https://www.juhe.cn/_t");
                return new JsonResult(model);
            }
        }
    }

    4.通过SwaggerUI界面调用接口测试结果

  • 相关阅读:
    python:封装连接数据库方法
    Python:self理解
    python:pytest优秀博客
    python:pytest中的setup和teardown
    python:单元测试框架pytest的一个简单例子
    java中的static关键字解析
    浅谈Java中的final关键字
    SpringMVC+Spring+Mybatis框架集成
    Mybatis学习总结(四)——输入映射和输出映射
    Mybatis学习总结(三)——SqlMapConfig.xml全局配置文件解析
  • 原文地址:https://www.cnblogs.com/pudefu/p/14715146.html
Copyright © 2011-2022 走看看