热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

GraphQL接口查询语言初步学习

AquerylanguageforyourAPI最近公司经常用到这东西,小编出于兴趣,学习一二,记录如下,如有不妥

A query language for your API

最近公司经常用到这东西,小编出于兴趣,学习一二,记录如下,如有不妥,还望多多指教。


一 概述

GraphQL是一种用于api的查询语言,在项目运行时对现有数据的一种查询方式。GraphQL为API中的数据提供了一个完整的、可理解的描述,允许客户端要求他们真正需要的东西,使API更容易随着时间的推移而发展,并支持强大的开发工具。

同级可对比APIJson,个人感觉apiJson在Java开发中比较实用和简单,如权限验证通过 @ MethodAccess 注解Model来添加角色对表的操作权限,以及支持远程函数调用,而相对比,graphql学习难度和成本以及规范性,都比较高。不过技多不压身,今天咱来看看。
(APIjson个人感觉可参考该博客,感觉还不错https://blog.csdn.net/u014618954/article/details/107021638/)


二 初步展示

graphql是api的查询语言,在一定程度上使开发更加高效和便捷,一下是一个例子。
例如,一个GraphQL服务告诉我们登录用户是谁(me)以及该用户的名字可能是这样的:
①创建
在这些类型上定义类型和字段,然后为每种类型的每个字段提供函数。

type Query {me: User
}type User {id: IDname: String
}

function Query_me(request) {return request.auth.user;
}function User_name(user) {return user.getName();
}

②查询

{me {name}
}

③返回

{"me": {"name": "Luke Skywalker"}
}

上述为查询query,可根据name查询所有对应名字的name,以及通过type,多参等查询优点,具体也不多说,可参考graphql官方文档,简单讲解分为三点,如下。

应用场景:
①多平台等原因导致的字段冗余
②一个页面多次调用聚合数据
③经常改动接口且精简逻辑


三 实际应用

讲了半天湿的,下面来点干货,本次演示Java和go两种语言的基本使用


3.1 java+spring boot+graphql

我们的示例应用程序将是一个简单的API,用于获取特定书籍的详细信息。

① 构建目录

Select:Gradle ProjectJavaSpring Boot 2.1.x
Project metadataGroup: com.graphql-java.tutorialArtifact: book-details
Dependencyweb

② 添加基础依赖


com.graphql-java:graphql-java:11.0 // NEW
com.graphql-java:graphql-java-spring-boot-starter-webmvc:1.0 // NEW
com.google.guava:guava:26.0-jre // NEW
org.springframework.boot:spring-boot-starter-web
org.springframework.boot:spring-boot-starter-test
}

③ 创建相关文件
在src/main/resources目录下创建 schema.graphqls

//该部分是一个关于书籍的基本类型的定义,并与后续类型的查询有关
type Query {bookById(id: ID): Book
}type Book {id: IDname: StringpageCount: Intauthor: Author
}type Author {id: IDfirstName: StringlastName: String
}

在com.graphqljava.tutorial.bookdetails目录下创建GraphQLProvider.class,并创建一个GraphQL实例:

@Component
public class GraphQLProvider {private GraphQL graphQL;@Beanpublic GraphQL graphQL() { return graphQL;// 这个GraphQL实例通过使用@Bean注释的GraphQL()方法公开为一个Spring Bean}@PostConstructpublic void init() throws IOException {//使用Guava资源从类路径读取文件URL url = Resources.getResource("schema.graphqls");//GraphQL Java Spring适配器将使用该GraphQL实例使我们的模式通过HTTP在默认url / String sdl = Resources.toString(url, Charsets.UTF_8);//创建一个GraphQLSchema和GraphQL实例GraphQLSchema graphQLSchema = buildSchema(sdl);this.graphQL = GraphQL.newGraphQL(graphQLSchema).build();}@AutowiredGraphQLDataFetchers graphQLDataFetchers;//抓取数据private GraphQLSchema buildSchema(String sdl) {TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(sdl);RuntimeWiring runtimeWiring = buildWiring();SchemaGenerator schemaGenerator = new SchemaGenerator();return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring);}/*buildWiring使用graphQLDataFetchers bean实际注册两个DataFetchers:一个用于检索具有特定ID的图书一个用于获取特定书籍的作者*/private RuntimeWiring buildWiring() {return RuntimeWiring.newRuntimeWiring().type(newTypeWiring("Query").dataFetcher("bookById", graphQLDataFetchers.getBookByIdDataFetcher())).type(newTypeWiring("Book").dataFetcher("author", graphQLDataFetchers.getAuthorDataFetcher())).build();}
}

重要的接口(不用自己创):
DataFetcher是一个带有单个方法的接口,它只接受DataFetcherEnvironment类型的单个参数;
当GraphQL Java执行查询时,它会为在查询中遇到的每个字段调用适当的数据表器。

public interface DataFetcher {T get(DataFetchingEnvironment dataFetchingEnvironment) throws Exception;
}

让我们假设有一个不匹配的图书映射有一个关键totalPages而不是pageCount。这将导致每本书的pageCount值为空,因为PropertyDataFetcher无法获取正确的值。为了解决这个问题,你必须为Book注册一个新的DataFetcher(本文案例不需要)

// 在 GraphQLDataFetchers class// 实现 DataFetcherpublic DataFetcher getPageCountDataFetcher() {return dataFetchingEnvironment -> {Map book = dataFetchingEnvironment.getSource();return book.get("totalPages");};}

创建一个新的类GraphQLDataFetchers,其中包含书籍和作者的示例列表

@Component
public class GraphQLDataFetchers {private static List> books = Arrays.asList(ImmutableMap.of("id", "book-1","name", "Harry Potter and the Philosopher's Stone","pageCount", "223","authorId", "author-1"),ImmutableMap.of("id", "book-2","name", "Moby Dick","pageCount", "635","authorId", "author-2"),ImmutableMap.of("id", "book-3","name", "Interview with the vampire","pageCount", "371","authorId", "author-3"));private static List> authors = Arrays.asList(ImmutableMap.of("id", "author-1","firstName", "Joanne","lastName", "Rowling"),ImmutableMap.of("id", "author-2","firstName", "Herman","lastName", "Melville"),ImmutableMap.of("id", "author-3","firstName", "Anne","lastName", "Rice"));public DataFetcher getBookByIdDataFetcher() {return dataFetchingEnvironment -> {String bookId = dataFetchingEnvironment.getArgument("id");return books.stream().filter(book -> book.get("id").equals(bookId)).findFirst().orElse(null);};}public DataFetcher getAuthorDataFetcher() {return dataFetchingEnvironment -> {Map book = dataFetchingEnvironment.getSource();String authorId = book.get("authorId");return authors.stream().filter(author -> author.get("id").equals(authorId)).findFirst().orElse(null);};}
}

加入application的main方法启动项目测试

package com.graphqljava.tutorial.bookdetails;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class BookDetailsApplication {public static void main(String[] args) {SpringApplication.run(BookDetailsApplication.class, args);}}

可通过网页版测试https://cpq-dev.ext.hp.com/playground
在这里插入图片描述
可以很清晰的拿到结果了
(该playground可自行安装相应测试软件,如postman,altair,本文使用网页版,如有问题可参考源码:https://github.com/graphql-java/tutorials)


3.2 Golang+graphql

① 安装相应支持

go get github.com/graphql-go/graphql

(此目录为path目录下,之前博客有讲导包问题,可前往浏览,如不知道自己项目path目录,可用 go Current GOPATH 命令查找)

② 应用举例
下面是一个简单的例子,它定义了一个带有hello字符串类型字段的模式和一个返回字符串世界的Resolve方法。对该模式执行GraphQL查询,结果输出以JSON格式打印

package mainimport ("encoding/json""fmt""log""github.com/graphql-go/graphql"
)func main() {// Schemafields := graphql.Fields{"hello": &graphql.Field{Type: graphql.String,Resolve: func(p graphql.ResolveParams) (interface{}, error) {return "world", nil},},}rootQuery := graphql.ObjectConfig{Name: "RootQuery", Fields: fields}schemaConfig := graphql.SchemaConfig{Query: graphql.NewObject(rootQuery)}schema, err := graphql.NewSchema(schemaConfig)if err != nil {log.Fatalf("failed to create new schema, error: %v", err)}// Queryquery := `{hello}`params := graphql.Params{Schema: schema, RequestString: query}r := graphql.Do(params)if len(r.Errors) > 0 {log.Fatalf("failed to execute graphql operation, errors: %+v", r.Errors)}rJSON, _ := json.Marshal(r)fmt.Printf("%s \n", rJSON) // {"data":{"hello":"world"}}
}

上述为简单示例,更多有趣复杂案例推荐可前往
https://github.com/graphql-go/graphql/tree/master/examples/
https://github.com/graphql-go/graphql/blob/master/graphql_test.go 学习

本人也是对graphql初步学习,也希望大佬多多提建议

本文参考学习于
https://graphql.org/官网及相关git源码

个人推荐https://blog.csdn.net/qq_41882147/article/details/82966783,挺详细,介绍也比较实际,可适合进阶学习


推荐阅读
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • PHP中的单例模式与静态变量的区别及使用方法
    本文介绍了PHP中的单例模式与静态变量的区别及使用方法。在PHP中,静态变量的存活周期仅仅是每次PHP的会话周期,与Java、C++不同。静态变量在PHP中的作用域仅限于当前文件内,在函数或类中可以传递变量。本文还通过示例代码解释了静态变量在函数和类中的使用方法,并说明了静态变量的生命周期与结构体的生命周期相关联。同时,本文还介绍了静态变量在类中的使用方法,并通过示例代码展示了如何在类中使用静态变量。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • 本文介绍了ASP.NET Core MVC的入门及基础使用教程,根据微软的文档学习,建议阅读英文文档以便更好理解,微软的工具化使用方便且开发速度快。通过vs2017新建项目,可以创建一个基础的ASP.NET网站,也可以实现动态网站开发。ASP.NET MVC框架及其工具简化了开发过程,包括建立业务的数据模型和控制器等步骤。 ... [详细]
  • Commit1ced2a7433ea8937a1b260ea65d708f32ca7c95eintroduceda+Clonetraitboundtom ... [详细]
  • 图像因存在错误而无法显示 ... [详细]
  • 本文介绍了如何使用jQuery和AJAX来实现动态更新两个div的方法。通过调用PHP文件并返回JSON字符串,可以将不同的文本分别插入到两个div中,从而实现页面的动态更新。 ... [详细]
  • Todayatworksomeonetriedtoconvincemethat:今天在工作中有人试图说服我:{$obj->getTableInfo()}isfine ... [详细]
  • 从零基础到精通的前台学习路线
    随着互联网的发展,前台开发工程师成为市场上非常抢手的人才。本文介绍了从零基础到精通前台开发的学习路线,包括学习HTML、CSS、JavaScript等基础知识和常用工具的使用。通过循序渐进的学习,可以掌握前台开发的基本技能,并有能力找到一份月薪8000以上的工作。 ... [详细]
  • Node.js学习笔记(一)package.json及cnpm
    本文介绍了Node.js中包的概念,以及如何使用包来统一管理具有相互依赖关系的模块。同时还介绍了NPM(Node Package Manager)的基本介绍和使用方法,以及如何通过NPM下载第三方模块。 ... [详细]
author-avatar
Roger_丨8_8
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有