当前位置: 移动技术网 > IT编程>开发语言>.net > .NET Core中使用HttpClient的正确姿势

.NET Core中使用HttpClient的正确姿势

2018年09月21日  | 移动技术网IT编程  | 我要评论

车俊调中央政法委,黑客组织anonymous,钓大鱼汉化版

前言

为了更方便在服务端调用 http 请求,微软在 .net framework 4.x 的时候引入了 httpclient。但 httpclient 有很多严重问题,一直饱受诟病,比如 infoq 的这篇文章 t.cn/evzy80y,吐槽了 httpclient 不能立即关闭连接、性能消耗严重等的问题。

http协议的重要性相信不用我多说了,httpclient相比传统jdk自带的urlconnection,增加了易用性和灵活性,它不仅是客户端发送http请求变得容易,而且也方便了开发人员测试接口(基于http协议的),即提高了开发的效率,也方便提高代码的健壮性。因此熟练掌握httpclient是很重要的必修内容,掌握httpclient后,相信对于http协议的了解会更加深入。

.net core 2.1 开始引入的 httpclientfactory 解决了 httpclient 的所有痛点。有了 httpclientfactory,我们不需要关心如何创建 httpclient,又如何释放它。通过它可以创建具有特定业务的 httpclient,而且可以很友好的和 di 容器结合使用,更为灵活。

下面以 asp.net core 为例介绍 httpclient 新的三种正确使用方式。

一、直接使用方式

不管是哪种方式,都要先注册服务,对于 asp.net core 应用则是在 startup.cs 文件的 configureservices 添加如果代码:

services.addhttpclient();

然后在 controller 中通过构造注入的试获得 ihttpclientfactory,然后通过它来创建 httpclient 对象。示例代码:

public class valuescontroller : basecontroller
{
 private readonly ihttpclientfactory _httpclientfactory;
 public valuescontroller(ihttpclientfactory httpclientfactory)
 {
  _httpclientfactory = httpclientfactory;
 }

 [httpget]
 public async task<actionresult> get()
 {
  var client = _httpclientfactory.createclient();
  client.baseaddress = new uri("http://api.github.com");
  string result = await client.getstringasync("/");
  return ok(result);
 }
}

这种使用方式适合一次性的 http 请求调用,弊端是如果多次都要请求 github 的接口,那就得写很多重复代码配置 httpclient。

二、命名式使用方式

命名式的使用方式可以解决第一种方式的问题,对于特定域名的 http 调用,可以只做一次配置,然后在多个地方通过名称拿到相同的 client 来使用。

首先在 startup.cs 注册服务的地方添加带有特定名称的 httpclient 服务,并添加需要的配置,如下示例:

services.addhttpclient();
services.addhttpclient("github", c =>
{
 c.baseaddress = new uri("https://api.github.com/");
 c.defaultrequestheaders.add("accept", "application/vnd.github.v3+json");
 c.defaultrequestheaders.add("user-agent", "httpclientfactory-sample");
});

注意这里添加了两次 addhttpclient,一次是没有命名的,一次是有命名的。在 controller 中的使用方式是:

public class valuescontroller : basecontroller
{
 private readonly ihttpclientfactory _httpclientfactory;

 public valuescontroller(ihttpclientfactory httpclientfactory)
 {
  _httpclientfactory = httpclientfactory;
 }

 [httpget]
 public async task<actionresult> get()
 {
  var client = _httpclientfactory.createclient("github");
  string result = await client.getstringasync("/");
  return ok(result);
 }
}

但如果使用很频繁,这种获取 client 的方式还是有一点麻烦。下面介绍第三种方式,可以在使用的时候方便一点,但配置要麻烦些。

三、类型化使用方式

类型化的使用方式可以预先把配置放到自定义的 httpclient 中,然后在需要的地方都过依赖注入直接拿到 httpclient 实例。

我们来看具体的例子,首先自定义一个 httclient 类,比如访问 github 接口的类可以这样定义:

public class githubclient
{
 public httpclient client { get; private set; }

 public githubclient(httpclient httpclient)
 {
  httpclient.baseaddress = new uri("https://api.github.com/");
  httpclient.defaultrequestheaders.add("accept", "application/vnd.github.v3+json");
  httpclient.defaultrequestheaders.add("user-agent", "httpclientfactory-sample");
  client = httpclient;
 }

 public async task<string> getdata()
 {
  return await _client.getstringasync("/");
 }
}

这里的 getdata 就是额外扩展的共用方法。使用前需要为这个类注册服务:

services.addhttpclient<githubclient>();

然后在需要的地方(比如 controller)中这样使用:

public class valuescontroller : basecontroller
{
 private readonly githubclient _githubclient;;

 public valuescontroller(githubclient githubclient)
 {
  _githubclient = githubclient;
 }

 [httpget]
 public async task<actionresult> get()
 {
  string result = await _githubclient.getdata();
  return ok(result);
 }
}

类型化的方式和命名式的方式相比,虽然在配置的时候会麻烦一点,但它有两个好处:一是不用通过名称字符串来获得 client,而是直接通过依赖注入获得具体的 client;二是可以在自定义的 httpclient 类中扩展共用的方法。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对移动技术网的支持。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网