引言

    相信巨硬,我们便一直硬。Net版本到现在已经出了7了,8也已经在预览版了,相信在一个半月就会正式发布,其中也有很多拭目以待的新功能了,不仅仅有Apm和Tap的结合,TaskToAscynResult,以及UnsafeAccessor用来获取私有变量,性能比反射,EMIT更高,还有针对AsyncLocal封装的IAsyncContext,IAsyncState,用来存异步上下文的一些数据,当然了,最让我期待的还是自带了一个OpenFeign,在看新增的东西的时候,其他的都觉得一般般,个人觉得哈,当看到这个AutoClient新增的包的时候,好奇心的驱使下,我点进去看了一下,哇,官网终于出这玩意了,使用简单,根据特性,然后使用Sg来生成我们对应的实现从而我们只需要定义一个接口,打上特性,就可以生成一个对应的代理类,调用远程Api接口,太令人心动,为此特地升级了VS,下载了Net8,体验新功能,接下来,我们就看看他的使用案例。附官网链接:https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.extensions.http.autoclient.autoclientattribute?view=dotnet-plat-ext-8.0

AutoClient

    在使用自带的OpenFeign的时候,我们还需要下载一个扩展包 Microsoft.Extensions.Http.AutoClient,当然还有 Microsoft.Extensions.Http的扩展包了,接下来我们定义一个接口,IBussiness,打上AutoClient特性,第一个参数是我们在注入Httpclient的时候,给的名字,我这里叫TestApi,这里会根据使用了AutoClient特性自定生成一个BussIness的类,在下图可以看到,自动生成了一个AutoClient.g.cs文件,里面的类就是Bussiness,其中包括了我们的TestPost方法以及路由信息,在上面的代码中,我们使用了Post特性,代表我们这个是Post请求,以及方法参数限制必须有一个CancellationToken,这个Post里面的内容,就是我另外一个项目种的接口地址。

  

builder.Services.AddHttpClient("TestApi",s=>s.BaseAddress=new Uri(" http://localhost:5062")); 
[AutoClient("TestApi")]
public interface IBussiness
{
[Post("/Test/TestPost")]
public Task<string> TestPost(CancellationToken cancellationToken);
}
// <auto-generated/>
#nullable enable
#pragma warning disable CS1591 // Compensate for https://github.com/dotnet/roslyn/issues/54103 namespace WebApplication1.Api
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Gen.AutoClient", "8.0.0.0")]
public class Bussiness : IBussiness
{
private static class Statics
{
public static readonly global::System.Net.Http.Headers.MediaTypeHeaderValue ApplicationJsonHeader = new("application/json")
{
CharSet = global::System.Text.Encoding.UTF8.WebName
}; public static readonly global::System.Net.Http.Headers.MediaTypeHeaderValue TextPlainHeader = new("text/plain")
{
CharSet = global::System.Text.Encoding.UTF8.WebName
}; public static readonly global::System.Uri UriTestPost = new("/Test/TestPost", global::System.UriKind.Relative);
public static readonly global::Microsoft.Extensions.Http.Telemetry.RequestMetadata RequestMetadataTestPost = new()
{
DependencyName = "Bussiness",
RequestName = "TestPost",
RequestRoute = "/Test/TestPost"
}; }
private readonly global::System.Net.Http.HttpClient _httpClient;
private readonly global::Microsoft.Extensions.Http.AutoClient.AutoClientOptions _autoClientOptions; public Bussiness(global::System.Net.Http.HttpClient httpClient, global::Microsoft.Extensions.Http.AutoClient.AutoClientOptions autoClientOptions)
{
_httpClient = httpClient;
_autoClientOptions = autoClientOptions;
} public async global::System.Threading.Tasks.Task<string> TestPost(global::System.Threading.CancellationToken cancellationToken)
{
var httpRequestMessage = new global::System.Net.Http.HttpRequestMessage()
{
Method = global::System.Net.Http.HttpMethod.Post,
RequestUri = Statics.UriTestPost,
}; try
{
global::Microsoft.Extensions.Telemetry.TelemetryExtensions.SetRequestMetadata(httpRequestMessage, Statics.RequestMetadataTestPost); return await SendRequest<string>("Bussiness", Statics.RequestMetadataTestPost.RequestRoute, httpRequestMessage, cancellationToken)
.ConfigureAwait(false);
}
finally
{
httpRequestMessage.Dispose();
}
} private async global::System.Threading.Tasks.Task<TResponse> SendRequest<TResponse>(
string dependencyName,
string path,
global::System.Net.Http.HttpRequestMessage httpRequestMessage,
global::System.Threading.CancellationToken cancellationToken)
where TResponse : class
{ var response = await _httpClient.SendAsync(httpRequestMessage, cancellationToken).ConfigureAwait(false); if (typeof(TResponse) == typeof(global::System.Net.Http.HttpResponseMessage))
{
return (response as TResponse)!;
} try
{
if (!response.IsSuccessStatusCode)
{
var error = await global::Microsoft.Extensions.Http.AutoClient.AutoClientHttpError.CreateAsync(response, cancellationToken).ConfigureAwait(false);
throw new global::Microsoft.Extensions.Http.AutoClient.AutoClientException(global::System.FormattableString.Invariant($"The '{dependencyName}' HTTP client failed with '{response.StatusCode}' status code."), path, error);
} if (typeof(TResponse) == typeof(string))
{
#if NET5_0_OR_GREATER
var rawContent = await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false);
#else
cancellationToken.ThrowIfCancellationRequested();
var rawContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
#endif return (rawContent as TResponse)!;
} var mediaType = response.Content.Headers.ContentType?.MediaType;
if (mediaType == "application/json")
{
var deserializedResponse = await global::System.Net.Http.Json.HttpContentJsonExtensions.ReadFromJsonAsync<TResponse>(response.Content, _autoClientOptions.JsonSerializerOptions, cancellationToken)
.ConfigureAwait(false);
if (deserializedResponse == null)
{
var error = await global::Microsoft.Extensions.Http.AutoClient.AutoClientHttpError.CreateAsync(response, cancellationToken).ConfigureAwait(false);
throw new global::Microsoft.Extensions.Http.AutoClient.AutoClientException(global::System.FormattableString.Invariant($"The '{dependencyName}' REST API failed to deserialize response."), path, error);
} return deserializedResponse;
} var err = await global::Microsoft.Extensions.Http.AutoClient.AutoClientHttpError.CreateAsync(response, cancellationToken).ConfigureAwait(false);
throw new global::Microsoft.Extensions.Http.AutoClient.AutoClientException(global::System.FormattableString.Invariant($"The '{dependencyName}' REST API returned an unsupported content type ('{mediaType}')."), path, err); }
finally
{
response.Dispose();
}
}
} [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Gen.AutoClient", "8.0.0.0")]
public static class AutoClientsExtensions
{
public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection AddBussiness(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services)
{
return services.AddBussiness(_ => { });
} public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection AddBussiness(
this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services,
global::System.Action<global::Microsoft.Extensions.Http.AutoClient.AutoClientOptions> configureOptions)
{
global::Microsoft.Extensions.DependencyInjection.OptionsServiceCollectionExtensions.AddOptionsWithValidateOnStart<global::Microsoft.Extensions.Http.AutoClient.AutoClientOptions, global::Microsoft.Extensions.Http.AutoClient.AutoClientOptionsValidator>(services, "Bussiness").Configure(configureOptions);
global::Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton<IBussiness>(services, provider =>
{
var httpClient = global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService<global::System.Net.Http.IHttpClientFactory>(provider).CreateClient("TestApi");
var autoClientOptions = global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService<global::Microsoft.Extensions.Options.IOptionsMonitor<global::Microsoft.Extensions.Http.AutoClient.AutoClientOptions>>(provider).Get("Bussiness");
return new Bussiness(httpClient, autoClientOptions);
});
return services;
} }
}

  下面这段代码,是我另一个项目接口的代码,可以看到,路由是Test,方法的路由是TestPost,返回了一个字符串true,因为,在使用AutoClient的时候,返回类型必须是引用类型,接下来,我们调用一下测试看看,在返回的结果中,我们可以看到返回了我们在另一个项目中返回的结果,true,同时,AutoClient还支持Get,Patch,Delete,Get,Put,Body(标记是在Body中),Header,Query等诸多特性,就是一个c#版本的OpenFeign,简直爽的不要不要的。

[Route("Test")]
public class TestController : ControllerBase
{
public TestController()
{ }
[HttpPost("TestPost")]
public Task<string> TestPost()
{
return Task.FromResult("true");
}
}

结语

    今天就要开始十月一假期了,后续节后来了,会持续带来新增api的一些玩法,包括IAsyncContext,还有其他的在等待探索,欢迎大家关注。

【c#版本Openfeign】Net8 自带OpenFeign实现远程接口调用的更多相关文章

  1. 微服务架构 | 4.2 基于 Feign 与 OpenFeign 的服务接口调用

    目录 前言 1. OpenFeign 基本知识 1.1 Feign 是什么 1.2 Feign 的出现解决了什么问题 1.3 Feign 与 OpenFeign 的区别与对比 2. 在服务消费者端开启 ...

  2. Git push将本地版本库的分支推送到远程服务器上对应的分支

    在使用git commit命令将修改从暂存区提交到本地版本库后,只剩下最后一步将本地版本库的分支推送到远程服务器上对应的分支了,如果不清楚版本库的构成,可以查看我的另一篇,git 仓库的基本结构. g ...

  3. 带SSL证书的httpclient 远程接口工具类

    package com.iups.wx.util; import java.io.IOException; import java.io.UnsupportedEncodingException; i ...

  4. iOS开发——iOS7(及以后版本) SDK自带二维码(含条形码)扫码、二维码生成

    本文转载至 http://www.cnblogs.com/leotangcn/p/4357907.html 现在很多APP都涉及了二维码扫码功能,这个功能简单实用,很多情况下用户乐于使用,现在本文带来 ...

  5. HTML5 + AJAX ( jQuery版本 ) 文件上传带进度条

    页面技术:HTML5 + AJAX ( jQuery) 后台技术:Servlet 3.0 服务器:Tomcat 7.0 jQuery版本:1.9.1 Servlet 3.0 代码 package or ...

  6. JENKINS的远程API调用,然后用PYTHON解析出最新的版本及稳定成功的版本

    这个功能,我觉得在作自动作部署时,是可以派上用处的. 记录一下. import urllib f = urllib.urlopen('http://jenkinsurl/job/job_name/ap ...

  7. Thinkphp 3.2及以上版本实现支付宝担保交易、即时到账接口类、函数和使用方法

    给客户开发网站时需要用到支付宝在线付款功能,小云到thinkphp网站溜了一圈,代码是有,可是都不怎么全,因此这篇文章诞生了! 本篇文章讲解了三个类的实现,担保交易.即时到账.双功能收款(该功能支付宝 ...

  8. Sonatype Nexus Repository Manager版本3.14.2访问控制缺失及远程代码执行漏洞

    发现被执行的程序在xmrig在 /var/tmp/目录下 ,脚本文件内容为以下: curl -o /var/tmp/xmrig http://202.144.193.159/xmrig;curl -o ...

  9. 接口测试——带token请求post接口(postman学习)

    今天遇到一个接口,是添加备注的,post类型,访问参数中需要带上token才行,我在header 中直接加token参数,接口总返回 403,请登陆 1.考虑yapi接口平台集成的是postman的接 ...

  10. jmeter处理带表单的接口请求

    如何用jmeter处理带选项的表单接口请求 下面是用到了F12 抓包的处理方法 下图是直接手动在页面上请求的结果 下面就是采用F12抓包抓到url 和FormData 分别把上面获取的url和Form ...

随机推荐

  1. 洛谷 P7579 「RdOI R2」称重(weigh) 题解

    题意: 题目 一道交互题. 有 n 个球,里面有两个假球,假球比普通球的要轻,每次可以询问任意两组球的轻重关系,第一组轻为 < ,第二组轻为 > ,一样重量为 = . 思路: 先考虑在一个 ...

  2. 理解ASP.NET Core - 全球化&本地化&多语言(Globalization and Localization)

    注:本文隶属于<理解ASP.NET Core>系列文章,请查看置顶博客或点击此处查看全文目录 概述 在众多知名品牌的网站中,比如微软官网.YouTube等,我们经常可以见到"切换 ...

  3. java匿名内部类的初解

    java原生态中的匿名内部类 1.匿名内部类的定义 使用匿名内部类的两种的方法 建立父类,重写父类的方法 实现接口的方法 2.普通类的实现 1. 普通类实现 实现普通类需要先声明对一个类的对象,再调用 ...

  4. DevOps|中式土味OKR与绩效考核落地与实践

    昨天一个小伙伴和我讨论了一下OKR和绩效管理,所以这次想简单明了地说下在中国怎么做比较合适,很多高大上的理论无法落地也是空中楼阁. 首先说一些,我个人的理解 道德品质和能力素质决定了一个人的职位行为 ...

  5. [ARM 汇编]高级部分—性能优化与调试—3.4.3 使用模拟器进行调试与测试

    在ARM汇编程序开发过程中,使用模拟器(emulator)进行调试和测试是一种非常有效的方法.模拟器可以在不同的处理器上测试代码,帮助我们发现潜在的问题,并提供丰富的调试功能.本节将介绍如何使用QEM ...

  6. AR技术的应用与未来

    目录 随着科技的不断进步,增强现实(AR)技术也在不断发展壮大.AR技术是一种通过计算机技术和传感器技术将虚拟信息融合到现实世界中的技术,可以为用户带来一种全新的.交互性更强的体验.本文将探讨AR技术 ...

  7. 手机号码吉利数PHP检测算法代码,超级实用

    手机号码吉利数理预测解读:将手机号码末尾的四个数字,先除以八十,再减去整数部分,只使用剩下的小数(小数点反面的数字)乘以八十,然后将所得结果,对表查阅,就知道吉凶.(换句话说就是余数)例如:手机尾号是 ...

  8. Seal AppManager如何基于Terraform简化基础设施管理

    作者简介 陈灿,数澈软件Seal 后端研发工程师,曾在腾讯负责敏捷研发体系建设以及 DevOps 解决方案的敏捷实践.在敏捷研发和产品效能提升有着丰富的经验,致力于构建一站式研发友好的平台工程解决方案 ...

  9. MySQL——GROUP BY详解与优化

    在 MySQL 中,GROUP BY用于将具有指定列中相同值的行分组在一起.这是在处理大量数据时非常有用的功能,允许对数据进行分类和聚合. 基本使用 语法 以下是GROUP BY子句的基本语法: &q ...

  10. 基于Linux的三种防火墙(IPtables、Firewall、UFW)

    学而不思则罔,思而不学则殆. 导航 IPtables Firewall UFW 对比总结 IPtables部分 1.IPtables 四表五链. 四表:filter.nat.raw.mangle. 五 ...