前言
为了更方便在服务端调用 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 类中扩展共用的方法。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。