.net core 2.2 中IHttpClientFactory的使用

在.net core中使用HttpClient请求api,有很多资源的问题,比如使用using的时候,虽然可以释放资源,但是套接字(socket)也不会立即释放,所以.net core2.1中,新增了IHttpClientFactory.将其用于配置和创建应用中的 HttpClient 实例。 这能带来以下好处:

  • 提供一个中心位置,用于命名和配置逻辑 HttpClient 实例。 例如,可注册和配置 github 客户端,使其访问 GitHub。 可以注册一个默认客户端用于其他用途。
  • 通过委托 HttpClient 中的处理程序整理出站中间件的概念,并提供适用于基于 Polly 的中间件的扩展来利用概念。
  • 管理基础 HttpClientMessageHandler 实例的池和生存期,避免在手动管理 HttpClient 生存期时出现常见的 DNS 问题。
  • (通过 ILogger)添加可配置的记录体验,以处理工厂创建的客户端发送的所有请求。

一、基本用法

在 Startup中的ConfigureServices中 

 services.AddHttpClient();
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using WebApplication1.Content;

namespace WebApplication1.Controllers
{
    public class TestController : Controller
    {
        private readonly IHttpClientFactory _clientFactory;public TestController(IHttpClientFactory clientFactory)
        {
            _clientFactory = clientFactory;
        }

        /// <summary>
        /// 基本用法
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<string> Get()
        {
            HttpClient client = _clientFactory.CreateClient();

            //方法一:
            HttpRequestMessage request = new HttpRequestMessage
            {
                Method = new HttpMethod("get"),
                RequestUri = new System.Uri("http://127.0.0.1:8067/api/values"),
            };
            HttpResponseMessage response = await client.SendAsync(request);
            string res = await response.Content.ReadAsStringAsync();
            return res;

            ////方法二:
            //string res = await client.GetStringAsync("http://127.0.0.1:8067/api/values/1");
            //return res;
        }public IActionResult Index()
        {
           var aa= Get();
            var bb = aa.Result;return View();
        }

    }
}

二、命名客户端

在 Startup中的ConfigureServices中 

//命名客户端
services.AddHttpClient("test", c =>
{
  c.BaseAddress = new Uri("http://127.0.0.1:8067");
});
/// <summary>
/// 命名客户端
/// </summary>
/// <returns></returns>
public async Task<string> Get()
{
  HttpClient client = _clientFactory.CreateClient("test");
  //注册名叫 "test" 的客户端时,已经指定了该客户端的请求基地址,所以这里不需要指定主机名了
  return await client.GetStringAsync("api/values");
 }

 三、类型化客户端

在 Startup中的ConfigureServices中 ,这里就是注入时配置HttpClient

 //类型化客户端
 services.AddHttpClient<TestHttpClient>(c =>
 {
     //可以在这里设置,也可以在构造函数设置.
    //c.BaseAddress = new System.Uri("http://127.0.0.1:8067");
 });

新建个类 TestHttpClient

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;

namespace WebApplication1.Content
{
    public class TestHttpClient
    {
        public HttpClient Client { get; set; }

        public TestHttpClient(HttpClient client)
        {
            client.BaseAddress = new System.Uri("http://127.0.0.1:8067");
            Client = client;
        }

        public async Task<string> Get(string url)
        {
            return await Client.GetStringAsync(url);
        }

        public async Task<HttpResponseMessage> Post<T>(string url,T t)
        {
            return await Client.PostAsJsonAsync(url,t);
        }
    }
}
 /// <summary>
 /// 类型化客户端
 /// </summary>
 /// <returns></returns>
 [HttpGet]
 public async Task<string> Get()
 {
     return await _client.Get("api/values");
 }

 public async Task<HttpResponseMessage> Post()
 {
     //若返回400  则原因可能是本地客户端参数与api参数不一致
     Text t = new Text() { value = "123" };
     return await _client.Post("api/values", t);
 }

 public IActionResult Index()
  {
  var aa= Get();
  var bb = aa.Result;
  var cc = Post();
  var dd = cc.Result;
  if (dd.IsSuccessStatusCode)
  {
  var res = dd.Content.ReadAsStringAsync();
  var ee= res.Result;
  }
  return View();
}

public class Text
{
   public string value { get; set; }
}

api这边就是默认的,改了个post 参数类型要一致

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace Api.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        // GET api/values
        [HttpGet]
        public ActionResult<IEnumerable<string>> Get()
        {
            return new string[] { "value1", "value2" };
        }

        // GET api/values/5
        [HttpGet("{id}")]
        public ActionResult<string> Get(int id)
        {
            return "value";
        }

        // POST api/values
        [HttpPost]
        public string Post([FromBody]Text value)
        {
            return "post method";
        }

        // PUT api/values/5
        [HttpPut("{id}")]
        public void Put(int id, [FromBody] string value)
        {
        }

        // DELETE api/values/5
        [HttpDelete("{id}")]
        public void Delete(int id)
        {
        }
    }
    public class Text
    {
        public string value { get; set; }
    }
}

可以将 HttpClient 完全封装在类型化客户端中。 不是将它公开为属性,而是可以提供公共方法,用于在内部调用 HttpClient

参考资料:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/http-requests?view=aspnetcore-2.2

原文地址:https://www.cnblogs.com/LiChen19951127/p/11328761.html