文章目录
一、GraphQL是什么?
GraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。
一个 GraphQL 服务是通过定义类型和类型上的字段来创建的,然后给每个类型上的每个字段提供解析函数。
二、GraphQL与Restful的区别
1.对比
1.restful一个接口只能返回一个资源,graphql一次可以获得多个资源
2.restful用不同的url来区分资源,graphql用类型区分资源
2.特点
1.请求需要的数据,不多不少。(Restful会返回所有的数据)
2.获取多个资源,只用一个请求
3.描述所有可能类型的系统,便于维护。
三、使用express和Graphql 搭建helloWorld
1.编辑HelloWord.js
1.先创建一个文件夹graphqltext,在文件夹里创建一个helloWord.js文件,代码如下
const express = require('express');
const {buildSchema} = require('graphql');
const grapqlHTTP = require('express-graphql');
// 定义schema,查询和类型
const schema = buildSchema(`
type Account {
name: String
age: Int
sex: String
department: String
}
type Query {
hello: String
accountName: String
age: Int
account: Account
}
`)
// 定义查询对应的处理器
const root = {
hello: () => {
return 'hello world';
},
accountName: () => {
return '张三丰';
},
age:()=>{
return 18;
},
account: ()=>{
return {
name: '李四光',
age: 18,
sex: '男',
department: '科学院'
}
}
}
const app = express();
app.use('/graphql', grapqlHTTP({
schema: schema,
rootValue: root,
graphiql: true
}))
app.listen(3000);
2.搭建环境
1.https://nodejs.org/en/ 在官网下载nodejs,进行安装
2.cmd进入graphqltext的目录,输入npm init -y 目的是为了生成packjson文件
3.npm install express graphql express-graphql -S 目的为了安装三个组件
4.安装完毕访问url localhost:3000/graphql
四、参数类型与参数传递
1.基本参数类型
1.1基本类型:String,Int,Float,Boolean和ID,可以在shema声明的时候直接使用
1.2类型 代表数组,例如: [int]代表整型数组
2.参数传递
2.1 和js传递参数一样,小括号定义形参,但是注意:参数需要定义类型
2.2 !(叹号)代表参数不能为空
type Query{
rollDice(numDice:Int!,numSides:Int) :[Int]
}
2.3核心代码
const schema = buildSchema(`
type Query {
getClassMates(classNo: Int!): [String]
}
`)
const root = {
getClassMates({ classNo}) {
const obj = {
31: ['张三', '李四', '王五'],
61: ['张大三', '李大四', '王大五']
}
return obj[classNo];
}
}
3.自定义参数类型
3.1GraphQL允许用户自定义参数类型,通常用来描述获取的资源的属性
3.2核心代码
// 定义schema,查询和类型
const schema = buildSchema(`
type Account {
name: String
age: Int
sex: String
department: String
salary(city: String): Int
}
type Query {
getClassMates(classNo: Int!): [String]
account(username: String): Account
}
`)
// 定义查询对应的处理器
const root = {
getClassMates({ classNo}) {
const obj = {
31: ['张三', '李四', '王五'],
61: ['张大三', '李大四', '王大五']
}
return obj[classNo];
},
account({ username}) {
const name = username;
const sex = 'man';
const age = 18;
const department = '开发部';
const salary = ({city}) => {
if(city === "北京" || city == "上海" || city == "广州" || city == "深圳") {
return 10000;
}
return 3000;
}
return {
name,
sex,
age,
department,
salary
}
}
}
GraphQL clients
1.如何在客户端访问graphql的接口
1.1在baseType.js中添加公开文件夹,供用户访问静态资源
app.use(express.static('public'))
1.2新建public文件夹,里面创建index.html
<!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>
<script>
function getData() {
const query = `
query Account($username: String, $city: String) {
account(username: $username) {
name
age
sex
salary(city: $city)
}
}
`
const variables = {username: '李大四', city: '深圳'}
fetch('/graphql', {
method: "POST",
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
query: query,
variables: variables
})
}).then(res => res.json)
.then(json => {
console.log(data);
})
}
</script>
</html>
六、使用Mutations修改数据
1.查询使用query,修改数据使用Mutation
mutation.js代码
const express = require('express');
const {buildSchema} = require('graphql');
const grapqlHTTP = require('express-graphql');
// 定义schema,查询和类型, mutation
const schema = buildSchema(`
input AccountInput {
name: String
age: Int
sex: String
department: String
}
type Account {
name: String
age: Int
sex: String
department: String
}
type Mutation {
createAccount(input: AccountInput): Account
updateAccount(id: ID!, input: AccountInput): Account
}
type Query {
accounts: [Account]
}
`)
const fakeDb = {};
// 定义查询对应的处理器
const root = {
accounts() {
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 updatedAccount = Object.assign({}, fakeDb[id], input);
fakeDb[id] = updatedAccount;
// 返回保存结果
return updatedAccount;
}
}
const app = express();
app.use('/graphql', grapqlHTTP({
schema: schema,
rootValue: root,
graphiql: true
}))
app.listen(3000);
七、认证与中间件
拦截器
const middleware = (req, res, next) => {
if(req.url.indexOf('/graphql') !== -1 && req.headers.cookie.indexOf('auth') === -1) {
res.send(JSON.stringify({
error: "您没有权限访问这个接口"
}));
return;
}
next();
}
app.use(middleware);
八、高级Constructing Types(提高可维护性,代码量上升)
1.使用GraphQLObjectType定义Type(类型)
1.原始代码
// 定义schema,查询和类型
const schema = buildSchema(`
type Account {
name: String
age: Int
sex: String
department: String
}
type Query {
account(username: String): Account
}
`)
2.高级代码
var AccountType = new graphql.GraphQLObjectType({
name: 'Account',
fields: {
name: { type: graphql.GraphQLString },
age: { type: graphql.GraphQLInt },
sex: { type: graphql.GraphQLString },
department: { type: graphql.GraphQLString }
}
});
2.使用GraphQLObjectType定义query(查询)
1.原始代码
// 定义schema,查询和类型
const schema = buildSchema(`
type Account {
name: String
age: Int
sex: String
department: String
}
type Query {
account(username: String): Account
}
`)
2.高级代码
var queryType = new graphql.GraphQLObjectType({
name: 'Query',
fields: {
account: {
type: AccountType,
// `args` describes the arguments that the `user` query accepts
args: {
username: { type: graphql.GraphQLString }
},
resolve: function (_, { username }) {
const name = username;
const sex = 'man';
const age = 18;
const department = '开发部';
return {
name,
sex,
age,
department
}
}
}
}
});
3.创建shema
var schema = new graphql.GraphQLSchema({ query: queryType});