gpt4 book ai didi

【c#版本Openfeign】Net8自带OpenFeign实现远程接口调用

转载 作者:我是一只小鸟 更新时间:2023-09-23 23:02:34 34 4
gpt4 key购买 nike

引言

    相信巨硬,我们便一直硬。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实现远程接口调用的文章就讲到这里了,如果你想了解更多关于【c#版本Openfeign】Net8自带OpenFeign实现远程接口调用的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com