Refit 原理解析:从初识到实践
在现代的分布式系统和微服务架构中,HTTP API 调用是不可或缺的一部分。为了简化 HTTP 请求的构建和解析,我们可以使用 Refit 这个强大的库。Refit 通过将 HTTP API 抽象为接口,使得调用远程服务变得非常简单和直观。
1. 初识 Refit
Refit 是一个用于 .NET 的类型安全的 REST 客户端库。它允许你通过定义一个接口来描述 HTTP API,并自动生成实现代码。Refit 的核心思想是将 HTTP API 调用抽象为接口方法,开发者只需要定义接口,Refit 会自动处理 HTTP 请求的构建、发送和响应的解析。
定义一个简单的 API 接口
public interface IUserRefitApi
{
[Get("/users/{id}")]
Task<User> GetUserAsync(int id);
}
在这个例子中,IUserRefitApi 接口描述了一个获取用户信息的 API。Refit 会根据接口定义自动生成 HTTP 请求代码。
2. Refit 的作用
Refit 的主要作用是简化 HTTP API 的调用。具体来说,Refit 可以帮助开发者:
- 1. 减少样板代码:不需要手动创建
HttpClient、构建请求、解析响应。 - 2. 提高代码可读性:通过接口定义 API,代码更加清晰和易于理解。
- 3. 增强类型安全:编译器会检查接口定义和返回值类型,减少运行时错误。
- 4. 支持异步操作:所有方法都支持
async/await,适合现代异步编程模式。 - 5. 灵活的配置:支持自定义序列化、添加请求头、处理错误等。
3. Refit 的原理
Refit 的工作原理可以分为以下几个步骤:
3.1 接口解析
Refit 通过反射解析接口定义,提取出 HTTP 方法(如 [Get]、[Post])、路径、参数等信息。
- • HTTP 方法:通过注解(如
[Get]、[Post])指定。 - • 路径:注解中的路径可以包含占位符(如
{username}),这些占位符会被方法的参数替换。 - • 参数:方法的参数可以绑定到路径、查询字符串、请求体等。
3.2 请求构建
Refit 根据接口定义构建 HTTP 请求。它会将方法的参数绑定到请求的路径、查询字符串、请求体等。
- • 路径参数:通过占位符替换。
- • 查询参数:通过
[Query]注解指定。 - • 请求体:通过
[Body]注解指定。
3.3 请求发送
Refit 使用 HttpClient 发送 HTTP 请求。它会将构建好的请求发送到指定的 API 端点。
3.4 响应解析
Refit 接收 HTTP 响应,并将其反序列化为方法的返回类型。默认情况下,Refit 使用 System.Text.Json 进行反序列化。
3.5 异常处理
如果 HTTP 请求失败(如返回 4xx 或 5xx 状态码),Refit 会抛出 ApiException,开发者可以捕获并处理这些异常。
4. Refit 的使用场景
Refit 适用于以下场景:
- 1. 调用 RESTful API:
- • 当你需要与外部服务(如第三方 API)进行通信时,Refit 可以简化 HTTP 请求的构建和解析。
- 2. 微服务架构:
- • 在微服务架构中,服务之间通常通过 HTTP 进行通信。Refit 可以帮助你快速创建类型安全的客户端,减少手动编写 HTTP 请求代码的工作量。
- 3. 移动应用和后端通信:
- • 在移动应用中,Refit 可以用于与后端服务进行通信,简化网络请求的逻辑。
- 4. 快速开发:
- • 当你需要快速测试或集成一个 API 时,Refit 可以让你在几分钟内完成 API 调用代码的编写。
- 5. 需要强类型支持的场景:
- • Refit 提供了强类型的 API 调用方式,避免了手动解析 JSON 或处理字符串的麻烦。
5.项目实践
5.1 安装 Refit
安装 Refit 的 NuGet 包:
dotnet add package Refit.HttpClientFactory
我们这里安装的是Refit.HttpClientFactory包,Refit 和 Refit.HttpClientFactory 是 Refit 库的两个不同部分,它们的作用和使用场景有所不同。
Refit 和 Refit.HttpClientFactory大致区别如下:
| 特性 | Refit 核心库 | Refit.HttpClientFactory |
|---|---|---|
| 依赖 | 直接依赖 HttpClient |
依赖 HttpClientFactory |
| 生命周期管理 | 需要手动管理 HttpClient |
|
| 生命周期 | 由 HttpClientFactory自动管理 |
|
| 依赖注入支持 | 不支持直接依赖注入 | 支持依赖注入 |
| 适用场景 | 简单的控制台应用或手动管理 | |
HttpClient |
ASP.NET Core 或其他依赖注入的应用 | |
| 配置灵活性 | 需要手动配置 HttpClient |
可以通过 HttpClientFactory配置 |
在 ASP.NET Core 中使用 Refit,推荐使用 Refit.HttpClientFactory,因为它与 HttpClientFactory 集成得更好,能够更灵活地配置和管理 HttpClient。
5.2 定义 API 接口
在项目中定义一个接口来描述你要调用的外部 API。我们将使用 /users 相关的端点。
using System.Collections.Generic;
using System.Threading.Tasks;
using Refit;
public interface IUserRefitApi
{
// 获取所有用户
[Get("/users")]
Task<List<User>> GetUsersAsync();
// 获取单个用户
[Get("/users/{id}")]
Task<User> GetUserAsync(int id);
// 创建新用户
[Post("/users")]
Task<User> CreateUserAsync([Body] User user);
// 更新用户
[Put("/users/{id}")]
Task<User> UpdateUserAsync(int id, [Body] User user);
// 删除用户
[Delete("/users/{id}")]
Task DeleteUserAsync(int id);
}
5.3 注册 Refit 客户端
在 Program.cs 中注册 Refit 客户端。你可以使用 HttpClientFactory 来管理 HttpClient 的生命周期。
using Microsoft.Extensions.DependencyInjection;
using Refit;
var builder = WebApplication.CreateBuilder(args);
// 添加 Refit 客户端
builder.Services.AddRefitClient<IUserRefitApi>()
.ConfigureHttpClient(c => c.BaseAddress = new Uri("https://******"));
var app = builder.Build();
// 配置中间件和路由
app.MapControllers();
app.Run();
5.4 在控制器中使用 Refit 客户端
在 Web API 的控制器中注入 Refit 客户端,并调用外部 API。
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
private readonly IUserRefitApi _userRefitApi;
public UsersController(IUserRefitApi userRefitApi)
{
_userRefitApi = userRefitApi;
}
// 获取所有用户
[HttpGet]
public async Task<IActionResult> GetUsers()
{
var users = await _userRefitApi.GetUsersAsync();
return Ok(users);
}
// 获取单个用户
[HttpGet("{id}")]
public async Task<IActionResult> GetUser(int id)
{
var user = await _userRefitApi.GetUserAsync(id);
return Ok(user);
}
// 创建新用户
[HttpPost]
public async Task<IActionResult> CreateUser([FromBody] User user)
{
var createdUser = await _userRefitApi.CreateUserAsync(user);
return Ok(createdUser);
}
// 更新用户
[HttpPut("{id}")]
public async Task<IActionResult> UpdateUser(int id, [FromBody] User user)
{
var updatedUser = await _userRefitApi.UpdateUserAsync(id, user);
return Ok(updatedUser);
}
// 删除用户
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteUser(int id)
{
await _userRefitApi.DeleteUserAsync(id);
return NoContent();
}
}
6. 扩展功能
6.1 添加请求头
可以通过 [Headers] 注解为接口或方法添加请求头:
[Headers("Authorization: Bearer TOKEN")]
public interface IUserRefitApi
{
[Get("/users")]
Task<List<User>> GetUsersAsync();
}
6.2 自定义序列化
可以通过 RefitSettings 自定义序列化行为:
builder.Services.AddRefitClient<IUserRefitApi>(new RefitSettings
{
ContentSerializer = new NewtonsoftJsonContentSerializer()
})
.ConfigureHttpClient(c => c.BaseAddress = new Uri("https://******"));
6.3 文件上传
Refit 支持文件上传。可以使用 [Multipart] 注解:
public interface IFileApi
{
[Multipart]
[Post("/upload")]
Task UploadFileAsync([AliasAs("file")] StreamPart file);
}
7. 总结
在 .NET Core Web API 中使用 Refit 可以极大地简化对外部 HTTP API 的调用。通过定义接口和注解,Refit 可以自动生成 HTTP 请求代码,并通过 HttpClientFactory 管理 HttpClient 的生命周期。无论是调用第三方 API 还是实现微服务通信,Refit 都是一个非常实用的工具。

Refit 原理解析:从初识到实践的更多相关文章
- Tengine HTTPS原理解析、实践与调试【转】
本文邀请阿里云CDN HTTPS技术专家金九,分享Tengine的一些HTTPS实践经验.内容主要有四个方面:HTTPS趋势.HTTPS基础.HTTPS实践.HTTPS调试. 一.HTTPS趋势 这一 ...
- vue.js响应式原理解析与实现
vue.js响应式原理解析与实现 从很久之前就已经接触过了angularjs了,当时就已经了解到,angularjs是通过脏检查来实现数据监测以及页面更新渲染.之后,再接触了vue.js,当时也一度很 ...
- tomcat原理解析(一):一个简单的实现
tomcat原理解析(一):一个简单的实现 https://blog.csdn.net/qiangcai/article/details/60583330 2017年03月07日 09:54:27 逆 ...
- Spring Boot干货系列:(三)启动原理解析
Spring Boot干货系列:(三)启动原理解析 2017-03-13 嘟嘟MD 嘟爷java超神学堂 前言 前面几章我们见识了SpringBoot为我们做的自动配置,确实方便快捷,但是对于新手来说 ...
- 基于OpenCV进行图像拼接原理解析和编码实现(提纲 代码和具体内容在课件中)
一.背景 1.1概念定义 我们这里想要实现的图像拼接,既不是如题图1和2这样的"图片艺术拼接",也不是如图3这样的"显示拼接",而是实现类似"BaiD ...
- APPcrawler基础原理解析及使用
一.背景 一年前,我们一直在用monkey进行Android 的稳定性测试 ,主要目的就是为了测试app 是否会产生Crash,是否会有ANR,页面错误等问题,在monkey测试过程中,实现了脱离Ca ...
- Spring Boot启动原理解析
Spring Boot启动原理解析http://www.cnblogs.com/moonandstar08/p/6550758.html 前言 前面几章我们见识了SpringBoot为我们做的自动配置 ...
- 第16 章 : 深入理解 etcd:基于原理解析
深入理解 etcd:基于原理解析 本文将主要分享以下三方面的内容: 第一部分,会为大家介绍 etcd 项目发展的整个历程,从诞生至今 etcd 经历的那些重要的时刻: 第二部分,会为大家介绍 etcd ...
- [原][Docker]特性与原理解析
Docker特性与原理解析 文章假设你已经熟悉了Docker的基本命令和基本知识 首先看看Docker提供了哪些特性: 交互式Shell:Docker可以分配一个虚拟终端并关联到任何容器的标准输入上, ...
- 【算法】(查找你附近的人) GeoHash核心原理解析及代码实现
本文地址 原文地址 分享提纲: 0. 引子 1. 感性认识GeoHash 2. GeoHash算法的步骤 3. GeoHash Base32编码长度与精度 4. GeoHash算法 5. 使用注意点( ...
随机推荐
- R数据分析:做量性研究的必备“家伙什”-furniture包介绍
In conjunction with many other tidy tools, the package should be useful for health, behavioral, and ...
- GraphQL Part II: 中间件
GraphQL Part II: 中间件 如果您熟悉 ASP.NET Core 的中间件,您可能注意到在我们上一篇博客中我们已经拥有了一个中间件.在初始的空白应用中,中间件的职责是返回 hello W ...
- 搭建 zerotier 的行星服务
放弃moon节点,直接搭建Zerotier根服务器_软件应用_什么值得买 Zerotier的优点在于其部署十分简便,只需在zerotier官网注册登陆并创建网络,在自己的设备安装客户端加入网络后,ze ...
- 重建sln的项目层级
编写包含多个 csproj 的程序时,随着项目数量的持续增加,可能涉及一些文件夹的变动,手动添加项目或者变动会变得非常麻烦,这个时候,可以利用 dotnet cli 帮助我们完成. 如果从零开始,我们 ...
- 干掉EasyExcel!FastExcel初体验
我们知道 EasyExcel 在作者从阿里离职之后就停止维护了,但在前两周 EasyExcel 原作者推出了他的升级版框架 FastExcel.以下是 FastExcel 的上手实战过程,带大家一起提 ...
- Debian关闭防火墙命令详解
防火墙是保护计算机系统安全的关键组件.在一些情况下,需要关闭防火墙,以允许特定的应用程序或服务访问网络.在Debian系统中关闭防火墙的方法多种多样,本文将从多个方面对Debian关闭防火墙命令进行详 ...
- Win10正式专业版激活方法
首先,我们先查看一下Win10正式专业版系统的激活状态: 点击桌面左下角的"Windows"按钮,从打开的扩展面板中依次点击"设置"-"更新和安全 ...
- Qt音视频开发40-ffmpeg采集桌面并录制
一.前言 之前用ffmpeg打通了各种视频文件和视频流以及本地摄像头设备的采集,近期有个客户需求要求将整个桌面屏幕采集下来,并可以录制保存成MP4文件,以前也遇到过类似的需求,由于没有搞过,也没有精力 ...
- OpenWrt安装腾讯云DDNS插件
1.插件介绍 OpenWRT TencentDDNS插件是一款腾讯云研发的,自动映射动态公网IP至用户指定的DNSPod域名解析记录的官方插件. 标题 名称 中文名称 腾讯云DDNS插件 英文名称 l ...
- 解决pip命令报错及Python环境配置指南:从安装到优化
1. 错误日志 当我在 Linux 机器(使用 Debian 或 Ubuntu 或衍生发行版)上运行 pip install xyz 时,会出现这样的错误: error: externally-man ...