GraphQL介绍

  • GraphQL是Facebook开发的一种数据查询语言,并于2015年公开发布。它是REST API的替代品。
  • GraphQL既是一种用于API的查询语言也是一个满足你数据查询的运行时。GraphQL对你的API的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且没有任何冗余,也让API更容易地随着时间推移而演进。
  • 官网:https://graphql.org/
  • 中文网:https://graphql.cn/
  • 特点:

1.请求需要的数据,不多不少
例如:account中有name,age,sex,department等,可以只取得需要的字段。
2.获取多个资源,只用一个请求
3.描述所有可能类型的系统。便于维护,根据需求平滑演进,添加或者隐藏字段。

例如一个查询请求:

//GraphQL语法,后面会讲到
//会根据字段进行数据的获取,而不像REST直接将所有的字段进行返回,这是一个特别好的前端优化的点
query{getAccount(userId:1){name //graphql语法会根据里面的字段取出对应的值agesex}
}

结果如下:

{“data”:{"getAccount":{"name":"xxx","age":"xxx","sex":"xxx"}}
}

GraphQL与restful对比

  1. restful:Representational State Transfer表属性状态转移。本质上就是用定义uri,通过api接口来取得资源。通用系统架构,不受语言限制。restful还是主流。
  2. 例子:饿了么接口


  3. restful一个接口只能返回一个资源,graphql一次可以获取多个资源。
  4. restful用不同的url来区分资源,graphql用类型区分资源。

使用express+GraphQL

  1. npm init -y //初始化一个package.json文件
  2. npm i express graphql express-graphql -S
  3. node helloWorld.js
  4. localhost:4000/graphql
  5. query{hello}
const express = require('express');
const graphqlHTTP = require('express-graphql');
const {buildSchema} = require('graphql');//Construct a schema,using GraphQL,schema language
//构建schema,这定义查询的语句和类型
const schema= buildSchema(type Account{name:Stringage:Intsex:String}type Query{hello:StringaccountName:Stringaccount:Account}
);//The root proyides a resolver function for each API
//定义查询所对应的resolver,也就是查询对应的处理器
const root={hello:()=>{return 'Hello World!';},accountName:()=>{return "test name";};account:()=>{return {name:"test name",age:11,sex:"test sex",}}
};const app = express();
app.use('/graphql',graphqlHTTP({schema:schema,rootValue:root,graphql:true,    //是否启用调试界面,false就不能调试了,开发时是true,上线的话变为false
}))
app.listen(4000);

类型定义与返回值不一致时会报错

基本参数类型

  • 基本类型:String/Int/Float/Boolean/ID。可以在schema声明的时候直接使用。
  • [类型]代表数组,例如:[Int]代表整型数组。

参数传递

  • 和js传递参数一样,小括号内定义形参,但是注意:参数需要定义类型。
  • !(叹号)代表参数不能为空
type Query{rollDice(numDice:Int!,numSides:Int):[Int]
}

Test Demo:


自定义参数类型

  • GraphQL允许用户自定义参数类型,通常用来描述要获取的资源的属性。
type Account{name:Stringage:Intsex:Stringsalary(city:String):Int
}
type Query{account(name:String):Account //定义一个Account属性,然后在Account类型中进行返回
}

GraphQL clients

  • 如何在客户端访问graphql的接口?
var username = 66;
//固定写法,Account($username:Int!),account(username:$username),$username和后端的username是一样的
var query = `query Account($username:Int!){account(username:$username)
}`;
fetch('/graphql',{method:'POST',headers:{'Content-Type':'application/json','Accept':'application/json',},//因为是post,数据从body出去body:JSON.stringify({query,variables:{username},})
})
.then(r=>r.json())
.then(data=>console.log('data returned',data));

后端代码

const express = require('express');
const {buildSchema} = require('graphql');
const graphql = require('express-graphql');
//定义schema,查询和类型
const schema = buildSchema(`type Account{name:Stringage:Intsex:Stringdepartment:Stringsalary(city:String):Int}type Query{getClassMates(classNo:Int!):[String]account(username:String):Account}
`)
//定义查询对应的处理器
const root={getClassMates({classNo}){const obj={31:['name1','name2','name3'],32:['name4','name5','name6']}return obj[classNo];},account({username}){const name=username;const sex='man';const age=11;const department='testdepartment';const salary=({city})=>{if(city==='北京'||city==='上海'||city==='广中'||city==='深圳'){return 10000;}return 2000;}return {name,sex,age,department,salary}}
}
const app=express();
app.use('/graphql',graphqlHTTP({schema:schema,rootValue:root,graphiql:true
}))
//公开文件夹,供用户访问静态资源
app.use(express.static("public")
app.listen(3000);

前端代码

  <!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head>
<body><button onclick="getData()">获取数据</button>
</body>
</html>
<script>function getData(){const query=`query Account($username:String,$city:String){account(username:$username){nameagesexsalary(city:$city)}}`const variables={username:"lisi",city:'深圳'}fetch('/graphql',{method:'POST',header:{'Content-Type':'application/json','Accept':'application/json'},body:JSON.stringify({query:query,variables:variables})}).then(res=>res.json).then(data=>{console.log(data);})}
</script>

使用Mutations修改数据

  • 查询使用query,修改数据使用Mutation
    `
//input表示输入input AccountInput{name:Stringage:Intsex:Stringdepartment:Stringsalary:Int}type Mutation{//括号里是形参createAccount(input:AccountInput):AccountupdateAccount(id:ID!,input:AccountInput):Account}

代码
小坑:

  1. 写mutation的话必须写query
const express = require('express');
const {buildSchema}=require('graphql');
const graphqlHTTP=require('express-graphql');
//定义schema,查询和类型,mutation
const schema=buildSchema(`input AccountInput{name:Stringage:Intsex:Stringdepartment:String}type Account{name:Stringage:Intsex:Stringdepartment:String}type Mutation{createAccount(input:AccountInput):AccountupdateAccount(id:ID!,input:AccountInput):Account}type Query{account:[Account]}
`)
const fakeDB={};
//定义查询对应的处理器
const root={account(){var arr=[];for(const key in fakeDB){arr.push(fakeDB[key])}return arr;},createAccount({input}){//相当于数据库的保存fakeDB[input.name]=input;//返回保存结果return fakeDB[input.name];},updateAccount({id,input}){//相当于数据库的更新const updateAccount=Object.assign({},fakeDB[id],input);fakeDB[id]=updateAccount;//返回数据库return updatedAccount;}
}
const app=express();
app.use('/graphql',graphqlHTTP({schema:schema,rootValue:root,graphiql:true
}))app.listen(3000)

认证与中间件(高级部分)

const express = require('express');
const {buildSchema}=require('graphql');
const graphqlHTTP=require('express-graphql');
//定义schema,查询和类型,mutation
const schema=buildSchema(`input AccountInput{name:Stringage:Intsex:Stringdepartment:String}type Account{name:Stringage:Intsex:Stringdepartment:String}type Mutation{createAccount(input:AccountInput):AccountupdateAccount(id:ID!,input:AccountInput):Account}type Query{account:[Account]}
`)
const fakeDB={};
//定义查询对应的处理器
const root={account(){var arr=[];for(const key in fakeDB){arr.push(fakeDB[key])}return arr;},createAccount({input}){//相当于数据库的保存fakeDB[input.name]=input;//返回保存结果return fakeDB[input.name];},updateAccount({id,input}){//相当于数据库的更新const updateAccount=Object.assign({},fakeDB[id],input);fakeDB[id]=updateAccount;//返回数据库return updatedAccount;}
}
const app=express();//增加一个判断权限的中间件const middleware=(req,res,next)=>{if(req.url.indexOf('/graphql')!=-1&&req.headers.cookie.indexOf('auth')){res.send(JSON.stringify({error:"您没有权限访问这个接口"}));return;}next();
}//使用中间件
app.use(middleware)app.use('/graphql',graphqlHTTP({schema:schema,rootValue:root,graphiql:true
}))app.listen(3000)

Constructing Types(高级部分)

  1. 使用GraphQLObjectType定义type(类型)
    意义:方便后期维护
  2. 使用GraphQLObjectType定义query(查询)


3. 创建schema

高级_与数据库结合实战

const express = require('express');
const {buildSchema
} = require('graphql');
const graphqlHTTP = require('express-graphql');
const mysql = require('mysql');
// https://www.npmjs.com/package/mysql
var pool = mysql.createPool({connectionLimit: 10,host: 'localhost',user: 'root',password: 'root',database: 'xxxx'
})//定义schema,查询和类型,mutation
const schema = buildSchema(`input AccountInput{name:Stringage:Intsex:Stringdepartment:String}type Account{name:Stringage:Intsex:Stringdepartment:String}type Mutation{createAccount(input:AccountInput):AccountdeleteAccount(id:ID):BooleanupdateAccount(id:ID!,input:AccountInput):Account}type Query{account:[Account]}
`)
const fakeDB = {};
//定义查询对应的处理器
const root = {account() {return new Promise((resolve,reject)=>{pool.query('select name,age,sex,department from account',(err,results)=>{if(err){console.log('error',err.message);return;}const arr=[];for(const i=0;i<results.length;i++){arr.push({name:results[i].name,sex:results[i].sex,age:results[i].age,department:results[i].department,})}resolve(results);})})},createAccount({input}) {const data = {name: input.name,sex: input.sex,age: input.age,department: input.department}return new Promise((resolve, reject) => {pool.query('insert into accout set ?', data, (err) => {if (err) {console.log('error',err.message);return;}//返回保存结果resolve(data);})})},updateAccount({id,input}) {const data=input;return new Promise((resolve,reject)=>{pool.query('update account set?where name=?',[data,id],(err)=>{if(err){console.log('err',err.message);return;}resolve(data);})})    },deleteAccount({id}){return new Promise((resolve,reject)=>{pool.query('delete account where name=?',[id],(err)=>{if(err){console.log("err",err.message)reject(false);return;}resolve(true);})})}
}
const app = express();
//增加一个判断权限的中间件
const middleware = (req, res, next) => {if (req.url.indexOf('/graphql') != -1 && req.headers.cookie.indexOf('auth')) {res.send(JSON.stringify({error: "您没有权限访问这个接口"}));return;}next();
}
//使用中间件
app.use(middleware)app.use('/graphql', graphqlHTTP({schema: schema,rootValue: root,graphiql: true
}))app.listen(3000)

学习视频:https://www.bilibili.com/video/av46200333?from=search&seid=9265460496338796424

【GraphQL】---GraphQL的基本使用相关推荐

  1. java通用象棋游戏_在通用国际象棋界面周围模拟GraphQL包装器

    java通用象棋游戏 The Universal Chess Interface (UCI) has been around a long time and used by many chess en ...

  2. Spring发布新成员:Spring GraphQL!高调出场的GraphQL能火起来了吗?

    7月6日,在GraphQL Java诞生6周年的时候,Spring社区通过博客宣布正式创建全新项目:Spring GraphQL,同时还发布了这个新项目的里程碑1.0版本. 博客原文:https:// ...

  3. GraphQL and Relay 浅析

    Facebook 在去年夏天公布了 GraphQL,就像往前端深潭砸下了一颗巨石,人们都被水声吸引到了湖边,观望是否会出现什么,有些人期待,有些人猜疑.过了半年多,社区已经慢慢的摸清这个石头的材质,本 ...

  4. Spring Boot + GraphQL 才是 API 的未来!

    前言 在浅尝GraphQL一文描述了GraphQL及基本使用,本文提供一个基本示例,描述如何基于spring boot的web项目快速应用. graphql-java的官方文档:Getting sta ...

  5. 干掉 RESTful!GraphQL 真香!

    -     前言    - REST作为一种现代网络应用非常流行的软件架构风格,自从Roy Fielding博士在2000年他的博士论文中提出来到现在已经有了20年的历史.它的简单易用性,可扩展性,伸 ...

  6. GraphQL(二):GraphQL服务搭建

    在GraphQL(一):GraphQL介绍中讲到目前已经有很多平台完成了GraphQL实现,这里以Java平台为例,介绍GraphQL服务的搭建. graphql-java + graphql-jav ...

  7. 扬言要干掉 RESTful API 的 GraphQL 是什么鬼?

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | toutiao.com/i6833818331 ...

  8. 精读《REST,GraphQL,Webhooks gRPC 如何选型》

    1 引言 每当项目进入联调阶段,或者提前约定接口时,前后端就会聚在一起热火朝天的讨论起来.可能 99% 的场景都在约定 Http 接口,讨论 URL 是什么,入参是什么,出参是什么. 有的团队前后端接 ...

  9. 实现根据id查询房源数据的GraphQL服务

    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...

  10. GraphQL入门之进一步了解GraphQL

    进一步了解GraphQL GraphQL很好的解决了RESTful在使用过程中的不足,接下来,我们进一步了解下它. 按需索取数据,避免浪费 演示地址:http://graphql.cn/learn/s ...

最新文章

  1. 第十七届智能车竞赛研讨会
  2. linux 音频路径,Linux系统中提取DVD音频的方法介绍(转)
  3. 自考总结-2019-4-14
  4. Packt.Java.9.High.Performance.2017.11
  5. [存储引擎基础知识]InnoDB与MyISAM的六大区别(非原创)
  6. 已知可生成0~4的rand5(),实现生成0~6的rand7()
  7. 【爬虫系列之一】爬虫开发环境的搭建
  8. php中mysqli 处理查询结果集的几个方法
  9. 笔刷怎么做_零基础怎么学板绘?板绘小白必备基础知识
  10. android——GestureDetector.OnGestureListener 手势详解
  11. kubernetes视频教程笔记 (3)-Pod及其网络通讯方式
  12. java ioutils 写入文件_IOUtils和FileUtils的学习笔记
  13. 什么是 GPL GNU,自由软件
  14. 上班两年干了些啥?该思考人生
  15. 一个简单的跑酷引擎-------bibibibi
  16. ElasticSearch高级功能的使用(模版查询、地理位置查询等)
  17. A-Unimodal Array
  18. Photoshop:使用层遮照制作图像渐变特效(2)
  19. Manjaro 20 安装/切换中文输入法
  20. 超微服务器安装操作系统,超微服务器bios设置

热门文章

  1. 2022网鼎杯青龙组wp
  2. openSUSE 多个GPU设置 深度学习 Caffe PyTorch 等
  3. OGG 抓取进程模式转换(集成模式→经典模式)(integrated→classic)
  4. AJAX请求和普通HTTP请求区别(postman分析)
  5. UnRaid利用iGVT-g插件实现Nas宿主机、虚拟机同时使用intel核显输出或硬解(硬件加速)功能
  6. 360笔试题2019年4月24日(彩球分篮子问题 )
  7. 可能是全网首个支持阿里云Elasticsearch Xapck鉴权的Skywalking
  8. prefetch()
  9. 「 科研经验 」思考“工程解决方案”的思维
  10. 表格table标签的属性及使用方式