造轮子之集成GraphQL
先简单对比以下GraphQL和WebAPI:
GraphQL和Web API(如RESTful API)是用于构建和提供Web服务的不同技术。
- 数据获取方式:
- Web API:通常使用RESTful API,客户端通过发送HTTP请求(如GET、POST、PUT、DELETE)来获取特定的数据。每个请求通常返回一个固定的数据结构,包含在响应的主体中。
- GraphQL:客户端可以使用GraphQL查询语言来精确指定需要的数据。客户端发送一个GraphQL查询请求,服务器根据查询的结构和字段来返回相应的数据。
- 数据获取效率:
- Web API:每个请求返回的数据通常是预定义的,无论客户端需要的数据量大小,服务器都会返回相同的数据结构。这可能导致客户端获取到不必要的数据,或者需要发起多个请求来获取所需数据。
- GraphQL:客户端可以精确指定需要的数据,避免了不必要的数据传输。客户端可以在一个请求中获取多个资源,并且可以根据需要进行字段选择、过滤、排序等操作,从而提高数据获取效率。
- 版本管理:
- Web API:通常使用URL版本控制或者自定义的HTTP头来管理API的版本。当API发生变化时,可能需要创建新的URL或者HTTP头来支持新的版本。
- GraphQL:GraphQL中没有显式的版本控制机制,而是通过向现有的类型和字段添加新的字段来扩展现有的API。这样可以避免创建多个不同版本的API。
- 客户端开发体验:
- Web API:客户端需要根据API的文档来构造请求和解析响应。客户端需要手动处理不同的API端点和数据结构。
- GraphQL:客户端可以使用GraphQL的强类型系统和自动生成的代码工具来进行开发。客户端可以根据GraphQL的模式自动生成类型定义和查询代码,提供了更好的开发体验和类型安全性。
在前面我们基础框架是基于WebAPI(REST FUL API)的模式去开发接口的,所有的响应数据都需要定义一个DTO结构,但是有些场景可能只需要某些字段,而后端又懒得定义新数据接口对接,这就会导致客户端获取到不必要的数据。在这种情况下,使用GraphQL就可以有较好的体验。
那么,在我们现有写好的Service中,如何快速集成GraphQL又无需复杂编码工作呢。这就是我们接下来要实现的了。
HotChocolate.AspNetCore
HotChocolate.AspNetCore是.NET一个老牌的GraphQL实现库,它可以让我们很快速的实现一个GraphQL Server。
安装HotChocolate.AspNetCore的nuget,在Program中添加代码
builder.Services.AddGraphQLServer()
app.MapGraphQL();
这样就完成一个GraphQLServer的集成。
启动程序,访问https://localhost:7080/graphql/ 可以看到集成的界面。可以使用这个界面操作测试我们的graphql查询。
实现QueryType
接下来实现一个基础的QueryType,用于扩展查询。
using HotChocolate.Authorization;
namespace Wheel.Graphql
{
[Authorize]
public class Query : IQuery
{
}
[InterfaceType]
public interface IQuery
{
}
}
在AddGraphQLServer()后面添加代码
builder.Services.AddGraphQLServer()
.AddQueryType<Query>()
;
使用ExtendObjectType扩展Query类,方便接口拆分。
public interface IQueryExtendObjectType
{
}
[ExtendObjectType(typeof(IQuery))]
public class SampleQuery : IQueryExtendObjectType
{
public List<string> Sample()
{
return new List<string> { "sample1", "sample2" };
}
}
[ExtendObjectType(typeof(IQuery))]
public class Sample2Query : IQueryExtendObjectType
{
public string Sample2(string id)
{
return id;
}
}
这里创建一个IQueryExtendObjectType空接口,用于获取所有需要扩展的QueryAPI
约定所有扩展的Query需要继承IQueryExtendObjectType接口,并加上ExtendObjectType特性标签。
封装AddGraphQLServer方法:
using HotChocolate.Execution.Configuration;
using System.Reflection;
namespace Wheel.Graphql
{
public static class GraphQLExtensions
{
public static IRequestExecutorBuilder AddWheelGraphQL(this IServiceCollection services)
{
var result = services.AddGraphQLServer()
.AddQueryType<Query>()
;
var abs = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll")
.Where(x => !x.Contains("Microsoft.") && !x.Contains("System."))
.Select(x => Assembly.Load(AssemblyName.GetAssemblyName(x))).ToArray();
var types = abs.SelectMany(ab => ab.GetTypes()
.Where(t => typeof(IQueryExtendObjectType).IsAssignableFrom(t) && typeof(IQueryExtendObjectType) != t));
if (types.Any())
{
result = result.AddTypes(types.ToArray());
}
return result;
}
}
}
遍历所有IQueryExtendObjectType并加入GraphQLServer。
启动项目访问https://localhost:7080/graphql/
可以看到SchemaDefinition自动生成了我们的两个查询。
添加授权
安装HotChocolate.AspNetCore.Authorization的Nuget包。
在services.AddGraphQLServer()后面添加代码.AddAuthorization()
using HotChocolate.Execution.Configuration;
using System.Reflection;
namespace Wheel.Graphql
{
public static class GraphQLExtensions
{
public static IRequestExecutorBuilder AddWheelGraphQL(this IServiceCollection services)
{
var result = services.AddGraphQLServer()
.AddAuthorization()
.AddQueryType<Query>()
;
var abs = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll")
.Where(x => !x.Contains("Microsoft.") && !x.Contains("System."))
.Select(x => Assembly.Load(AssemblyName.GetAssemblyName(x))).ToArray();
var types = abs.SelectMany(ab => ab.GetTypes()
.Where(t => typeof(IQueryExtendObjectType).IsAssignableFrom(t) && typeof(IQueryExtendObjectType) != t));
if (types.Any())
{
result = result.AddTypes(types.ToArray());
}
return result;
}
}
}
未登录前执行查询,可以看到响应Error。
获取一个token之后配置一下:
再次请求,可以看到正常查询。
集成现有Service
改造一下SampleQuery
[ExtendObjectType(typeof(IQuery))]
public class SampleQuery : IQueryExtendObjectType
{
public async Task<List<GetAllPermissionDto>> Sample([Service] IPermissionManageAppService permissionManageAppService)
{
var result = await permissionManageAppService.GetPermission();
return result.Data;
}
}
打开https://localhost:7080/graphql/ 执行查询,可以看到正常返回。
当我们需要过滤不查询某些字段时,只需要修改Query查询格式。
分页查询,添加一下User的分页查询代码。
public class SampleQuery : IQueryExtendObjectType
{
public async Task<List<GetAllPermissionDto>> Sample([Service] IPermissionManageAppService permissionManageAppService)
{
var result = await permissionManageAppService.GetPermission();
return result.Data;
}
public async Task<Page<UserDto>> SampleUser(UserPageRequest pageRequest, [Service] IUserManageAppService userManageAppService)
{
var result = await userManageAppService.GetUserPageList(pageRequest);
return result;
}
}
测试:
可以看到,很简单就可以把现有的API转换成GraphQL。只不过一些排序分页逻辑我们没有采用GraphQL的方式,而是使用我们自己的WebApi分页查询的模式。
轮子仓库地址https://github.com/Wheel-Framework/Wheel
欢迎进群催更。

造轮子之集成GraphQL的更多相关文章
- 避免重复造轮子的UI自动化测试框架开发
一懒起来就好久没更新文章了,其实懒也还是因为忙,今年上半年的加班赶上了去年一年的加班,加班不息啊,好了吐槽完就写写一直打算继续的自动化开发 目前各种UI测试框架层出不穷,但是万变不离其宗,驱动PC浏览 ...
- GitHub Android 最火开源项目Top20 GitHub 上的开源项目不胜枚举,越来越多的开源项目正在迁移到GitHub平台上。基于不要重复造轮子的原则,了解当下比较流行的Android与iOS开源项目很是必要。利用这些项目,有时能够让你达到事半功倍的效果。
1. ActionBarSherlock(推荐) ActionBarSherlock应该算得上是GitHub上最火的Android开源项目了,它是一个独立的库,通过一个API和主题,开发者就可以很方便 ...
- 除非你是BAT,前端开发中最好少造轮子
站在前人的肩膀上 HTML.CSS.JavaScript是前端的根基,这是无可否认的事实.正如一辆车当然都是由一堆钢板和螺钉组成的,但是现在还有人拎着个锤子敲敲打打的造车吗?李书福说过,“汽车不过是四 ...
- Meteva——让预报检验不再重复造轮子
更多精彩,请点击上方蓝字关注我们! 检验是什么?****预报准确率的客观表达 说到天气预报,你最先会想到什么? 早上听了预报,带了一天伞却没下一滴雨的调侃? 还是 "蓝天白云晴空万里突然暴风 ...
- 54 个官方 Spring Boot Starters 出炉!别再重复造轮子了…….
在之前的文章,栈长介绍了 Spring Boot Starters,不清楚的可以点击链接进去看下. 前段时间 Spring Boot 2.4.0 也发布了,本文栈长再详细总结下最新的 Spring B ...
- 【疯狂造轮子-iOS】JSON转Model系列之二
[疯狂造轮子-iOS]JSON转Model系列之二 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇<[疯狂造轮子-iOS]JSON转Model系列之一> ...
- 【疯狂造轮子-iOS】JSON转Model系列之一
[疯狂造轮子-iOS]JSON转Model系列之一 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 之前一直看别人的源码,虽然对自己提升比较大,但毕竟不是自己写的,很容易遗 ...
- h5engine造轮子
基于学习的造轮子,这是一个最简单,最基础的一个canvas渲染引擎,通过这个引擎架构,可以很快的学习canvas渲染模式! 地址:https://github.com/RichLiu1023/h5en ...
- 我为什么还要造轮子?欠踹?Monk.UI表单美化插件诞生记!
背景 目前市场上有很多表单美化的UI,做的都挺不错,但是他们都有一个共同点,那就是90%以上都是前端工程师开发的,导致我们引入这些UI的时候,很难和程序绑定.所以作为程序员的我,下了一个决定!我要自己 ...
- 「iOS造轮子」之UIButton 用Block响应事件
俗语说 一个不懒的程序员不是好程序员 造轮子,也只是为了以后更好的coding. coding,简易明了的代码更是所有程序员都希望看到的 无论是看自己的代码,还是接手别人的代码 都希望一看都知道这代码 ...
随机推荐
- Linux 可执行文件瘦身指令 strip 使用示例
以下内容为本人的学习笔记,如需要转载,请声明原文链接微信公众号「ENG八戒」https://mp.weixin.qq.com/s/lJ8vj-FszEoplMVcmT0I0w 在 Linux 系统下开 ...
- 白嫖一个WebAPI限流解决方案
什么是API限流: API 限流是限制用户在一定时间内 API 请求数量的过程.应用程序编程接口 (API) 充当用户和软件应用程序之间的网关.例如,当用户单击社交媒体上的发布按钮时,点击该按钮会触发 ...
- 电子表格vlookup函数使用
vlookup是常用的辅助查找函数,但是这个函数的参数定义和解释非常的难以理解,即使用向导也很难搞清楚哪个参数是啥意思.放到编程圈里面应该也算bad design的典型了.下面是函数的定义,每次看到这 ...
- MySQL到ClickHouse数据同步方案
MySQL 同步到 ClickHouse的方案可以看下面的说明,选择合适最近的同步方法. 1. 对比结果概述 整体上,NineData(官网:www.ninedata.cloud )的数据复制功能在功 ...
- C# 中的 数组[]、ArrayList、List
C# 中的 数组[].ArrayList.List 数组 在 C# 中,数组实际上是对象,而不只是如在 C 和 C++ 中的连续内存的可寻址区域. 属性: 数组可以是一维.多维或交错的. 创建数组实例 ...
- Gin+Xterm.js实现远程Kubernetes Pod(一)
Xterm.js简介 xterm.js (https://xtermjs.org/)是一个开源的 JavaScript 库,它模拟了一个终端接口,可以在网页中嵌入一个完全功能的终端.这个库非常灵活,并 ...
- Linux中对管道命令中的任意子命令进行返回码校验
~~ linux return code with pipeline~~ ~~ linux 管道命令中的返回码~~ BASH SHELL中,通常使用 $? 来获取上一条命令的返回码. Shell Sc ...
- nodejs端模块化方式comomjs详解
nodejs端实现模块化的方式通常是通过commonjs,使用模块化可以复用js代码,使得逻辑结构更为清晰. commonjs的语法规则如下通过 module.exports 或者 exports 导 ...
- jmeter:内存溢出解决办法
使用jmeter执行性能测试,报错:java.lang.OutOfMemoryError: Java heap space 需要对jmeter的jvm进行调优.记录如下: 1. 问题记录及分析: 使用 ...
- Protobuf vs JSON
Protobuf(Protocol Buffers)和 JSON 都是数据序列化格式,但它们在许多方面有着显著的不同.以下是对两者的一些主要比较: 数据大小和速度: Protobuf:由于 Proto ...