【GraphQL】---GraphQL的基本使用
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对比
- restful:Representational State Transfer表属性状态转移。本质上就是用定义uri,通过api接口来取得资源。通用系统架构,不受语言限制。restful还是主流。
- 例子:饿了么接口
- restful一个接口只能返回一个资源,graphql一次可以获取多个资源。
- restful用不同的url来区分资源,graphql用类型区分资源。
使用express+GraphQL
- npm init -y //初始化一个package.json文件
- npm i express graphql express-graphql -S
- node helloWorld.js
- localhost:4000/graphql
- 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}
代码
小坑:
- 写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(高级部分)
- 使用GraphQLObjectType定义type(类型)
意义:方便后期维护
- 使用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的基本使用相关推荐
- java通用象棋游戏_在通用国际象棋界面周围模拟GraphQL包装器
java通用象棋游戏 The Universal Chess Interface (UCI) has been around a long time and used by many chess en ...
- Spring发布新成员:Spring GraphQL!高调出场的GraphQL能火起来了吗?
7月6日,在GraphQL Java诞生6周年的时候,Spring社区通过博客宣布正式创建全新项目:Spring GraphQL,同时还发布了这个新项目的里程碑1.0版本. 博客原文:https:// ...
- GraphQL and Relay 浅析
Facebook 在去年夏天公布了 GraphQL,就像往前端深潭砸下了一颗巨石,人们都被水声吸引到了湖边,观望是否会出现什么,有些人期待,有些人猜疑.过了半年多,社区已经慢慢的摸清这个石头的材质,本 ...
- Spring Boot + GraphQL 才是 API 的未来!
前言 在浅尝GraphQL一文描述了GraphQL及基本使用,本文提供一个基本示例,描述如何基于spring boot的web项目快速应用. graphql-java的官方文档:Getting sta ...
- 干掉 RESTful!GraphQL 真香!
- 前言 - REST作为一种现代网络应用非常流行的软件架构风格,自从Roy Fielding博士在2000年他的博士论文中提出来到现在已经有了20年的历史.它的简单易用性,可扩展性,伸 ...
- GraphQL(二):GraphQL服务搭建
在GraphQL(一):GraphQL介绍中讲到目前已经有很多平台完成了GraphQL实现,这里以Java平台为例,介绍GraphQL服务的搭建. graphql-java + graphql-jav ...
- 扬言要干掉 RESTful API 的 GraphQL 是什么鬼?
点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | toutiao.com/i6833818331 ...
- 精读《REST,GraphQL,Webhooks gRPC 如何选型》
1 引言 每当项目进入联调阶段,或者提前约定接口时,前后端就会聚在一起热火朝天的讨论起来.可能 99% 的场景都在约定 Http 接口,讨论 URL 是什么,入参是什么,出参是什么. 有的团队前后端接 ...
- 实现根据id查询房源数据的GraphQL服务
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...
- GraphQL入门之进一步了解GraphQL
进一步了解GraphQL GraphQL很好的解决了RESTful在使用过程中的不足,接下来,我们进一步了解下它. 按需索取数据,避免浪费 演示地址:http://graphql.cn/learn/s ...
最新文章
- 第十七届智能车竞赛研讨会
- linux 音频路径,Linux系统中提取DVD音频的方法介绍(转)
- 自考总结-2019-4-14
- Packt.Java.9.High.Performance.2017.11
- [存储引擎基础知识]InnoDB与MyISAM的六大区别(非原创)
- 已知可生成0~4的rand5(),实现生成0~6的rand7()
- 【爬虫系列之一】爬虫开发环境的搭建
- php中mysqli 处理查询结果集的几个方法
- 笔刷怎么做_零基础怎么学板绘?板绘小白必备基础知识
- android——GestureDetector.OnGestureListener 手势详解
- kubernetes视频教程笔记 (3)-Pod及其网络通讯方式
- java ioutils 写入文件_IOUtils和FileUtils的学习笔记
- 什么是 GPL GNU,自由软件
- 上班两年干了些啥?该思考人生
- 一个简单的跑酷引擎-------bibibibi
- ElasticSearch高级功能的使用(模版查询、地理位置查询等)
- A-Unimodal Array
- Photoshop:使用层遮照制作图像渐变特效(2)
- Manjaro 20 安装/切换中文输入法
- 超微服务器安装操作系统,超微服务器bios设置
热门文章
- 2022网鼎杯青龙组wp
- openSUSE 多个GPU设置 深度学习 Caffe PyTorch 等
- OGG 抓取进程模式转换(集成模式→经典模式)(integrated→classic)
- AJAX请求和普通HTTP请求区别(postman分析)
- UnRaid利用iGVT-g插件实现Nas宿主机、虚拟机同时使用intel核显输出或硬解(硬件加速)功能
- 360笔试题2019年4月24日(彩球分篮子问题 )
- 可能是全网首个支持阿里云Elasticsearch Xapck鉴权的Skywalking
- prefetch()
- 「 科研经验 」思考“工程解决方案”的思维
- 表格table标签的属性及使用方式