热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ASP.NETCore使用IHttpClientFactory的发起HTTP请求

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

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

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

具体使用案列如下,(本案列只简单封装了最常用的GET和POST请求方式,其他PUT、DELETE、PATCH如有需要请自行添加实现。)

代码中使用了Newtonsoft.Json。

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

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

 

 2.基于IHttpClientFactory的Helper类封装。 

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace Research.Web.Common
{
///


/// 本案列只简单封装了最常用的GET和POST请求方式,其他PUT、DELETE、PATCH,请自行添加实现。
///

public class HttpClientHelper
{
private IHttpClientFactory _httpClientFactory;
public HttpClientHelper(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
///
/// 发起GET异步请求
///

/// 返回类型
///


///

请求地址
///

请求头信息
///

请求超时时间,单位秒
/// 返回string
public async Task GetAsync(string url, Dictionary 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;
}
}
}
}
///


/// 发起GET异步请求
///

/// 返回类型
///


///

请求地址
///

请求头信息
///

请求超时时间,单位秒
/// 返回T
public async Task GetAsync(string url, Dictionary headers = null, int timeOut = 30) where T : new()
{
string respOnseString= await GetAsync(url, headers, timeOut);
if (!string.IsNullOrWhiteSpace(responseString))
{
return JsonConvert.DeserializeObject(responseString);
}
else
{
return default(T);
}
}
///


/// 发起POST异步请求
///

///


///

请求地址
///

POST提交的内容
///

POST内容的媒体类型,如:application/xml、application/json
///

HTTP响应上的content-type内容头的值,如:application/xml、application/json、application/text、application/x-www-form-urlencoded等
///

请求头信息
///

请求超时时间,单位秒
/// 返回string
public async Task PostAsync(string url, string body,
string bodyMediaType = null,
string respOnseContentType= null,
Dictionary 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]);
}
}
var 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;
}
}
}
}
///


/// 发起POST异步请求
///

/// 返回类型
///


///

请求地址
///

POST提交的内容
///

POST内容的媒体类型,如:application/xml、application/json
///

HTTP响应上的content-type内容头的值,如:application/xml、application/json、application/text、application/x-www-form-urlencoded等
///

请求头信息
///

请求超时时间,单位秒
/// 返回T
public async Task PostAsync(string url, string body,
string bodyMediaType = null,
string respOnseContentType= null,
Dictionary 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(responseString);
}
else
{
return default(T);
}
}
#region 私有函数
///


/// 获取请求的主机名
///

///


///
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;
///


/// 从DI容器中获取HttpClientHelper实列对象
///

///


public WebeController(HttpClientHelper httpClientHelper)
{
this._httpClientHelper = httpClientHelper;
}
///


/// 测试异步HttpClient
///

///
[HttpGet("testhttpasync")]
public async Task TestAsyncHttpClientFactory()
{
var model = await _httpClientHelper.GetAsync("https://www.juhe.cn/_t");
return new JsonResult(model);
}
}
}

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

 



推荐阅读
author-avatar
小镇七公主
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有