Refit在ASP.NET Core中的实践

Refit在ASP.NET Core中的实践,第1张

概述前言声名式服务调用,己经不算是一个新鲜的话题了,毕竟都出来好些年了。下面谈谈,最近项目中用到一个这样的组件的简单实践。目前部分项目用到的是Refit这个组件,都是配合HttpClientFactory来使用的。关于HttpClientFactory的一些简单介绍,可以参见官方文档,也可以看看前面的两篇比较粗略的相关介绍。也简单介绍一下背景,目前主要有两类的API接口:第一类是注册到Eureka中的,可以通过服务发现的方式来请求的,这里的都是新的接口。第二类是原始的接口,不能走服务发现,只能通过直连请求的方式来调用,这里的都是些老接口。换句话就是说,要同时兼容这两类接口。由于用HttpClientFactory集成服务发现十分简单,所以优先选了一个本身就带有HttpClientFactory的组件--Refit。什么是RefitRefit是一个自动类型安全的REST库,是RESTful架构的.NET客户端实现,它基于Attribute,提供了把REST API返回的数据转化为(Plain Ordinary C# Object,简单C#对象),POCO to JSON,网络请求(POST,GET,PUT,DELETE等)封装,内部封装使用HttpClient,前者专注于接口的封装,后者专注于网络请求的高效,二者分工协作。我们的应用程序通过 refit请求网络,实际上是使用 refit接口层封装请求参数、Header、Url 等信息,之后由 HttpClient完成后续的请求 *** 作,在服务端返回数据之后,HttpClient将原始的结果交给 refit,后者根据用户的需求对结果进行解析的过程。更多细节可以参考Refit的官网创建一个可调用的API接口直接上控制器的代码了〜〜// GET: api/persons[HttpGet]public IEnumerable<Person> Get(){return new List<Person>{new Person{Id = 1 , Name = "catcher wong", CreateTime = DateTime.Now},new Person{Id = 2 , Name = "james li", CreateTime = DateTime.Now.AddDays(-2)}};}// GET api/persons/5[HttpGet("{id}")]public Person Get(int id){return new Person { Id = id, Name = "name" };}// POST api/persons[HttpPost]public Person Post([FromBody]Person person){if (person == null) return new Person();return new Person { Id = person.Id, Name = person.Name };}// PUT api/persons/5[HttpPut]public string Put([FromBody]int id){return $"put {id}";}// DELETE api/persons/5[HttpDelete("{id}")]public string Delete(int id){return $"del {id}";}Refit的使用先通过Nuget安装Refit的包。然后就是定义我们的interface了public interface IPersonsApi{[Get("/api/persons")]Task<List<Person>> GetPersonsAsync();[Get("/api/persons/{id}")]Task<Person> GetPersonAsync([AliasAs("id")]int personId);[Post("/api/persons")]Task<Person> AddPersonAsync([Body]Person person);[Put("/api/persons")]Task<string> EditPersonAsync([Body]int id);[Delete("/api/persons/{id}")]Task<string> DeletePersonAsync(int id);}来看看这个interface里面涉及到的部分内容。Get,Post等特性就表明了接口的请求方式,后面的值就是请求的相对路径。相对路径中,可以使用占位符,来动态更新参数值。如果方法名和请求参数名不一致,需要用AliasAs指明。通过Body特性声明一个对象作为请求体发送到服务器返回值定义是Task或者IObservable然后是配合HttpClientFactory再通过Nuget安装一下Refit.HttpClientFactory如果PersonApi是注册到Euerka的,可以再添加Steeltoe的引用。public void ConfigureServices(IServiceCollection services){services.AddRefitClient<IPersonsApi>().ConfigureHttpClient(options =>{options.BaseAddress = new Uri(Configuration.GetValue<string>("personapi_url"));//other settings of httpclient})//Steeltoe discovery//.AddHttpMessageHandler<DiscoveryHttpMessageHandler>();services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);}前面在定义IPersonApi的时候,我们只指定了相对路径,而请求IP并没有指定,这里是放到ConfigureHttpClient里面去指定了。同时根据不同环境,配置不同的appsettings.{env}.json,达到切换的效果。同样的,如果想走服务发现,只需要放开注释的AddHttpMessageHandler,同时修改BaseeAddress为服务名的形式就可以了。说了这么多,都还只是配置阶段,下面就来看看具体怎么用。为了演示方便,就不在建一个Service层了,直接在控制器调用一下。用法也很简单,直接在控制器注入一下就可以使用了。[Route("api/[controller]")][ApiController]public class ValuesController : ControllerBase{private readonly IPersonsApi _api;public ValuesController(IPersonsApi api){this._api = api;}// GET api/values[HttpGet]public async Task<List<Person>> GetAsync(){return await _api.GetPersonsAsync();}// GET api/values/5[HttpGet("{id}")]public async Task<Person> Get(int id){return await _api.GetPersonAsync(id);}// POST api/values[HttpPost]public async Task<Person> Post([FromBody] Person value){return await _api.AddPersonAsync(value);}}到这里,代码层面的东西已经处理完了。下面来看看使用Refit效果(这里只看两个Get请求的):都是能正常拿到我们期望的结果。最后再看看输出的日志,确认一下。首先是访问/api/values的确确实实是向我们前面的PersonApi发起了请求。然后是访问/api/values/5555 的可见我们上面的别名(AliasAs)是起了效果的,能拼成正确的请求地址。至于其他类型的请求,这里就不演示了,让大家自己去尝试一下吧。总结Refit用起来还是比较简单的,运行了一段时间也还表现正常!当然本文介绍的也只是一些基本的用法!它还具有不错的扩展性,可以让我们根据自身需求做一些定制化的东西。本文的示例代码RefitClientApi

<h2 ID="前言">前言

声名式服务调用,己经不算是一个新鲜的话题了,毕竟都出来好些年了。

下面谈谈,最近项目中用到一个这样的组件的简单实践。

目前部分项目用到的是这个组件,都是配合HttpClientFactory来使用的。

关于HttpClientFactory的一些简单介绍,可以参见官方文档,也可以看看前面的两篇比较粗略的相关介绍。

也简单介绍一下背景,目前主要有两类的API接口:

第一类是注册到Eureka中的,可以通过服务发现的方式来请求的,这里的都是新的接口。

第二类是原始的接口,不能走服务发现,只能通过直连请求的方式来调用,这里的都是些老接口。

换句话就是说,要同时兼容这两类接口。

由于用HttpClientFactory集成服务发现十分简单,所以优先选了一个本身就带有HttpClientFactory的组件--Refit。

Refit是一个自动类型安全的REST库,是RESTful架构的.NET客户端实现,

它基于Attribute,提供了把REST API返回的数据转化为(Plain Ordinary C# Object,简单C#对象),POCO to JSON,网络请求(POST,GET,PUT,DELETE等)封装,内部封装使用HttpClient,前者专注于接口的封装,后者专注于网络请求的高效,二者分工协作。

我们的应用程序通过 refit请求网络,实际上是使用 refit接口层封装请求参数、Header、Url 等信息,之后由 HttpClient完成后续的请求 *** 作,在服务端返回数据之后,HttpClient将原始的结果交给 refit,后者根据用户的需求对结果进行解析的过程。

更多细节可以参考Refit的

直接上控制器的代码了〜〜

// GET: API/persons[httpGet]public IEnumerable Get(){    return new List    {        new Person{ID = 1,name = "catcher wong",CreateTime = DateTime.Now},new Person{ID = 2,name = "james li",CreateTime = DateTime.Now.AddDays(-2)}    };}

// GET API/persons/5
[httpGet("{ID}")]
public Person Get(int ID)
{
return new Person { ID = ID,name = "name" };
}

// POST API/persons
[httpPost]
public Person Post([FromBody]Person person)
{
if (person == null) return new Person();

return new Person { <a href="https://m.jb51.cc/tag/ID/" target="_blank" >ID</a> = person.<a href="https://m.jb51.cc/tag/ID/" target="_blank" >ID</a>,<a href="https://m.jb51.cc/tag/name/" target="_blank" >name</a> = person.<a href="https://m.jb51.cc/tag/name/" target="_blank" >name</a> };

}

// PUT API/persons/5
[httpPut]
public string Put([FromBody]int ID)
{
return $"put {ID}";
}

// DELETE API/persons/5
[httpDelete("{ID}")]
public string Delete(int ID)
{
return $"del {ID}";
}


<h2 ID="refit的使用">Refit的使用

先通过Nuget安装Refit的包。

然后就是定义我们的interface了

public interface IPersonsAPI{    [Get("/API/persons")]    Task> GetPersonsAsync();
[Get("/<a href="https://m.jb51.cc/tag/API/" target="_blank" >API</a>/persons/{<a href="https://m.jb51.cc/tag/ID/" target="_blank" >ID</a>}")]Task<Person> GetPersonAsync([A<a href="https://m.jb51.cc/tag/li/" target="_blank" >li</a>asAs("<a href="https://m.jb51.cc/tag/ID/" target="_blank" >ID</a>")]int person<a href="https://m.jb51.cc/tag/ID/" target="_blank" >ID</a>);[Post("/<a href="https://m.jb51.cc/tag/API/" target="_blank" >API</a>/persons")]Task<Person> AddPersonAsync([Body]Person person);[Put("/<a href="https://m.jb51.cc/tag/API/" target="_blank" >API</a>/persons")]Task<string> EditPersonAsync([Body]int <a href="https://m.jb51.cc/tag/ID/" target="_blank" >ID</a>);[Delete("/<a href="https://m.jb51.cc/tag/API/" target="_blank" >API</a>/persons/{<a href="https://m.jb51.cc/tag/ID/" target="_blank" >ID</a>}")]Task<string> DeletePersonAsync(int <a href="https://m.jb51.cc/tag/ID/" target="_blank" >ID</a>);

}

来看看这个interface里面涉及到的部分内容。

Get,Post等特性就表明了接口的请求方式,后面的值就是请求的相对路径。相对路径中,可以使用占位符,来动态更新参数值。如果方法名和请求参数名不一致,需要用AliasAs指明。通过Body特性声明一个对象作为请求体发送到服务器返回值定义是Task或者IObservable

然后是配合httpClIEntFactory

再通过Nuget安装一下Refit.httpClIEntFactory

如果PersonAPI是注册到Euerka的,可以再添加Steeltoe的引用。

public voID ConfigureServices(IServiceCollection services){    services.AddRefitClIEnt()            .ConfigurehttpClIEnt(options =>            {                options.BaseAddress = new Uri(Configuration.GetValue("personAPI_url"));                //other settings of httpclIEnt            })            //Steeltoe discovery            //.AddhttpMessageHandler()            ;
services.AddMvc().SetCompatibi<a href="https://m.jb51.cc/tag/li/" target="_blank" >li</a>tyVersion(Compatibi<a href="https://m.jb51.cc/tag/li/" target="_blank" >li</a>tyVersion.Version_2_1);

}

前面在定义IPersonAPI的时候,我们只指定了相对路径,而请求IP并没有指定,这里是放到ConfigurehttpClIEnt里面去指定了。

同时根据不同环境,配置不同的appsettings.{env}.Json,达到切换的效果。

同样的,如果想走服务发现,只需要放开注释的AddhttpMessageHandler,同时修改BaseeAddress为服务名的形式就可以了。

说了这么多,都还只是配置阶段,下面就来看看具体怎么用。

为了演示方便,就不在建一个Service层了,直接在控制器调用一下。

用法也很简单,直接在控制器注入一下就可以使用了。

[Route("API/[controller]")][APIController]public class ValuesController : ControllerBase{    private Readonly IPersonsAPI _API;    public ValuesController(IPersonsAPI API)    {        this._API = API;    }
// GET <a href="https://m.jb51.cc/tag/API/" target="_blank" >API</a>/values[<a href="https://m.jb51.cc/tag/http/" target="_blank" >http</a>Get]pub<a href="https://m.jb51.cc/tag/li/" target="_blank" >li</a>c async Task<<a href="https://m.jb51.cc/tag/List/" target="_blank" >List</a><Person>> GetAsync(){    return await _<a href="https://m.jb51.cc/tag/API/" target="_blank" >API</a>.GetPersonsAsync();                             }// GET <a href="https://m.jb51.cc/tag/API/" target="_blank" >API</a>/values/5[<a href="https://m.jb51.cc/tag/http/" target="_blank" >http</a>Get("{<a href="https://m.jb51.cc/tag/ID/" target="_blank" >ID</a>}")]pub<a href="https://m.jb51.cc/tag/li/" target="_blank" >li</a>c async Task<Person> Get(int <a href="https://m.jb51.cc/tag/ID/" target="_blank" >ID</a>){    return await _<a href="https://m.jb51.cc/tag/API/" target="_blank" >API</a>.GetPersonAsync(<a href="https://m.jb51.cc/tag/ID/" target="_blank" >ID</a>);}// POST <a href="https://m.jb51.cc/tag/API/" target="_blank" >API</a>/values[<a href="https://m.jb51.cc/tag/http/" target="_blank" >http</a>Post]pub<a href="https://m.jb51.cc/tag/li/" target="_blank" >li</a>c async Task<Person> Post([FromBody] Person value){    return await _<a href="https://m.jb51.cc/tag/API/" target="_blank" >API</a>.AddPersonAsync(value);}

}

到这里,代码层面的东西已经处理完了。

下面来看看使用Refit效果(这里只看两个Get请求的):

都是能正常拿到我们期望的结果。

最后再看看输出的日志,确认一下。

首先是访问/API/values

确确实实是向我们前面的PersonAPI发起了请求。

然后是访问/API/values/5555

可见我们上面的别名(AliasAs)是起了效果的,能拼成正确的请求地址。

至于其他类型的请求,这里就不演示了,让大家自己去尝试一下吧。

Refit用起来还是比较简单的,运行了一段时间也还表现正常!

当然本文介绍的也只是一些基本的用法!它还具有不错的扩展性,可以让我们根据自身需求做一些定制化的东西。

本文的示例代码href="https://github.com/catcherwong/Demos/tree/master/src/CallAPIsDemo/RefitClIEntAPI">RefitClIEntAPI

总结

以上是内存溢出为你收集整理的Refit在ASP.NET Core中的实践全部内容,希望文章能够帮你解决Refit在ASP.NET Core中的实践所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1256032.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存