GraphQL 学习
一、什么是GraphQL
一种用于 API 的查询语言
二、学习GraphQL
开始撸码学习
1.写一个 server.js 文件
const express = require('express');
const graphqlHTTP = require('express-graphql');
const {buildSchema} = require('graphql');
const schema = buildSchema(`
type Query {
hello: String
}
`);
const root = {hello: () => 'Hello world!'};
const app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
app.listen(4000, () => console.log('Now browse to localhost:4000/graphql'));
使用命令
1. 使用 npm init -y 初始化一个 package.json 文件
2. 安装所需插件 npm install express express-graphql graphql -S
![《GraphQL 学习》](http://ddrvcn.oss-cn-hangzhou.aliyuncs.com/2019/9/aaqMJv.png)
![《GraphQL 学习》](http://ddrvcn.oss-cn-hangzhou.aliyuncs.com/2019/9/bimmmy.png)
遇上错误如上:项目名称不能使用 grapql,修改成 my-graphql
2.启动项目测试
命令: node server.js
![《GraphQL 学习》](http://ddrvcn.oss-cn-hangzhou.aliyuncs.com/2019/9/7RzEvm.png)
遇上端口占用问题,停掉或者改用其他端口。
![《GraphQL 学习》](http://ddrvcn.oss-cn-hangzhou.aliyuncs.com/2019/9/EvuqUv.png)
相关命令:
lsof -i :4000
kill -9 端口号(上图为,47806)
![《GraphQL 学习》](http://ddrvcn.oss-cn-hangzhou.aliyuncs.com/2019/9/NnUbu2.png)
如上所示,启动成功。
访问地址: localhost:4000/graphql
![《GraphQL 学习》](http://ddrvcn.oss-cn-hangzhou.aliyuncs.com/2019/9/aaQbyy.png)
访问成功
3.定义复杂类型
定义一个 学生类型 student
const express = require('express');
const graphqlHTTP = require('express-graphql');
const {buildSchema} = require('graphql');
const schema = buildSchema(`
type Student{
name:String
age:Int
}
type Query {
hello: String
name:String
student:Student
}
`);
const root = {
hello: () => 'Hello world!',
name:()=>{
return 'zhangbf'
},
student:()=>{
return {
name:'张三丰',
age:18
}
}
};
const app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
app.listen(4000, () => console.log('Now browse to localhost:4000/graphql'));
运行结果
![《GraphQL 学习》](http://ddrvcn.oss-cn-hangzhou.aliyuncs.com/2019/9/a2eYNj.png)
4. 定义参数类型
新建一个 baseType.js文件
const express = require('express');
const graphqlHTTP = require('express-graphql');
const {buildSchema} = require('graphql');
const schema = buildSchema(`
type Query {
getClassMates(classNo:Int):[String]
}
`);
const root = {
getClassMates({classNo}) {
const obj = {
301: ['张三丰', '张翠山', '殷素素'],
61: ['张大三', '李大四', '王大五'],
};
return obj[classNo];
}
};
const app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
app.listen(4000, () => console.log('Now browse to localhost:4000/graphql'));
运行该文件 node baseType.js
在浏览器查看结果,如下
![《GraphQL 学习》](http://ddrvcn.oss-cn-hangzhou.aliyuncs.com/2019/9/zErYr2.png)
示例二
const express = require('express');
const graphqlHTTP = require('express-graphql');
const {buildSchema} = require('graphql');
const schema = buildSchema(`
type Student{
name:String
sex:String
age:Int
grade(number:Int):String
}
type Query {
getClassMates(classNo:Int):[String]
student(username:String):Student
}
`);
const root = {
getClassMates({classNo}) {
const obj = {
301: ['张三丰', '张翠山', '殷素素'],
601: ['张无忌', '赵敏', '周芷若'],
};
return obj[classNo];
},
student({username}){
const name=username;
const sex="男";
const age=20;
const grade=({number})=>{
if(number>60){
return "及格了"
}else{
return "垃圾"
}
};
return {
name,
sex,
age,
grade
}
}
};
const app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
app.listen(4000, () => console.log('Now browse to localhost:4000/graphql'));
![《GraphQL 学习》](http://ddrvcn.oss-cn-hangzhou.aliyuncs.com/2019/9/3aE7Zn.png)
三、使用GraphQL
1.在客户端访问graphql的接口
1.1 允许静态资源访问目录
app.use(express.static('public'));
![《GraphQL 学习》](http://ddrvcn.oss-cn-hangzhou.aliyuncs.com/2019/9/E3UzIv.png)
1.2 在 public 目录下添加 index.html 文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>graphql 客户端访问接口</title>
</head>
<body>
<button onclick="getData()">获取数据</button>
</body>
<script>
function getData() {
const query = `
query Student($username:String,$number:Int){
student(username:$username){
name
age
sex
grade(number:$number)
}
}
`;
const variables = {username: '张三丰', number: 56};
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(json);
})
}
</script>
</html>
1.3 重新启动
node baseType.js
1.4 查看访问结果
![《GraphQL 学习》](http://ddrvcn.oss-cn-hangzhou.aliyuncs.com/2019/9/yA773i.png)
2. 在客户端修改数据
创建一个文件,用于测试 插入数据、更新数据。
2.1 新建一个 mutation.js 文件
创建一个 mutation.js 文件
const express = require('express');
const graphqlHTTP = require('express-graphql');
const {buildSchema} = require('graphql');
const schema = buildSchema(`
input StudentInput{
name:String
age:Int
sex:String
grade:Int
}
type Student{
name:String
age:Int
sex:String
grade:Int
}
type Mutation{
createStudent(input:StudentInput):Student
updateStudent(id:ID!,input:StudentInput):Student
}
type Query{
student:[Student]
}
`);
const fakeDb = {};//数据库对象
const root = {
student() {
const arr = [];
for (const index in fakeDb) {
arr.push(fakeDb[index]);
}
return arr;
},
createStudent({input}) {
//类似保存到数据库
fakeDb[input.name] = input;
//返回保存结果
return fakeDb[input.name];
},
updateStudent({id, input}) {
//保存在一个对象里面
const updateStudent = Object.assign({}, fakeDb[id], input);
fakeDb[id] = updateStudent;
//返回对象
return updateStudent;
}
};
const app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
app.listen(4000, () => console.log('Now browse to localhost:4000/graphql'));
2.2 执行查看结果
node mutation.js
![《GraphQL 学习》](http://ddrvcn.oss-cn-hangzhou.aliyuncs.com/2019/9/ryeER3.png)
2.3 认证中间件
创建一个 middleware.js 文件,用于测试
const express = require('express');
const graphqlHTTP = require('express-graphql');
const {buildSchema} = require('graphql');
const schema = buildSchema(`
input StudentInput{
name:String
age:Int
sex:String
grade:Int
}
type Student{
name:String
age:Int
sex:String
grade:Int
}
type Mutation{
createStudent(input:StudentInput):Student
updateStudent(id:ID!,input:StudentInput):Student
}
type Query{
student:[Student]
}
`);
const fakeDb = {};//数据库对象
const root = {
student() {
const arr = [];
for (const index in fakeDb) {
arr.push(fakeDb[index]);
}
return arr;
},
createStudent({input}) {
//类似保存到数据库
fakeDb[input.name] = input;
//返回保存结果
return fakeDb[input.name];
},
updateStudent({id, input}) {
//保存在一个对象里面
const updateStudent = Object.assign({}, fakeDb[id], input);
fakeDb[id] = updateStudent;
//返回对象
return updateStudent;
}
};
const app = express();
const middleware = (req, res, next) => {
if (req.url.indexOf('/graphql') !== -1 && req.headers.cookie.indexOf('auth') === -1) {
res.send(JSON.stringify({
error: '您没有权限访问该接口'
}));
return false;
}
//放行
next();
};
//注册中间件
app.use(middleware);
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
app.listen(4000, () => console.log('Now browse to localhost:4000/graphql'));
![《GraphQL 学习》](http://ddrvcn.oss-cn-hangzhou.aliyuncs.com/2019/9/YvqmU3.png)
添加 auth值
![《GraphQL 学习》](http://ddrvcn.oss-cn-hangzhou.aliyuncs.com/2019/9/ARzYBr.png)
3. 使用ConstructingTypes 类型
为了便于维护,使用 ConstructingTypes 类型
1.创建 constructingTypes.js 测试文件
const express = require('express');
const graphqlHTTP = require('express-graphql');
const graphql = require('graphql');
var StudentType = new graphql.GraphQLObjectType({
name: "Student",
fields: {
name: {type: graphql.GraphQLString},
age: {type: graphql.GraphQLInt},
sex: {type: graphql.GraphQLString},
grade: {type: graphql.GraphQLInt},
}
});
var queryType = new graphql.GraphQLObjectType({
name: 'Query',
fields: {
student: {
type: StudentType,
args: {
username: {type: graphql.GraphQLString}
},
resolve: function (_, {username}) {
const name = username;
const sex = '男';
const age = 18;
const grade = 20;
return {
name,
sex,
age,
grade
}
}
}
}
});
var schema = new graphql.GraphQLSchema({query: queryType});
const app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
app.listen(4000, () => console.log('Now browse to localhost:4000/graphql'));
查看运行结果
![《GraphQL 学习》](http://ddrvcn.oss-cn-hangzhou.aliyuncs.com/2019/9/r22EZz.png)
四.与数据库相结合
1.创建测试数据库 test
在 test数据库下面 创建 student 表
![《GraphQL 学习》](http://ddrvcn.oss-cn-hangzhou.aliyuncs.com/2019/9/QBb2Mj.png)
2.在安装mysql插件
在 npmjs.com 网站找 mysql
安装
npm install mysql2 -S
3. 创建 database.js 测试文件
const express = require('express');
const graphqlHTTP = require('express-graphql');
const {buildSchema} = require('graphql');
const mysql = require('mysql2');
//https://www.npmjs.com/package/mysql2 mysql
//连接数据库
const connection = mysql.createConnection({
host: 'localhost', //数据库访问地址
user: 'root', //数据库用户
password: 'root', //数据库访问密码
database: 'test' //数据库
});
const schema = buildSchema(`
input StudentInput{
name:String
age:Int
sex:String
grade:Int
}
type Student{
name:String
age:Int
sex:String
grade:Int
}
type Mutation{
createStudent(input:StudentInput):Student
deletedStudent(id:ID!):Boolean
updateStudent(id:ID!,input:StudentInput):Student
}
type Query{
student:[Student]
}
`);
const root = {
student() {
//查询操作
return new Promise((resolve, reject) => {
connection.query('select name,sex,age,grade from student', (err, results) => {
if (err) {
console.log(results);
console.log('出错了:' + err);
return false;
}
const arr = [];
for (let i = 0; i < results.length; i++) {
arr.push({
name: results[i].name,
sex: results[i].sex,
age: results[i].age,
grade: results[i].grade,
})
}
resolve(arr);
})
});
},
createStudent({input}) {
//保存到数据库
const data = {
name: input.name,
age: input.age,
sex: input.sex,
grade: input.grade,
};
return new Promise((resolve, reject) => {
connection.query('insert into student set ?', data, (err,results) => {
if (err) {
console.log(results);
console.log('出错了:' + err.message);
return false;
}
resolve(data);
});
});
},
updateStudent({id, input}) {
//更新操作
const data = input;
return new Promise((resolve, reject) => {
connection.query('update student set ? where name=?', [data, id], (err,results) => {
if (err) {
console.log(results);
console.log('出错了:' + err.message);
return false;
}
resolve(data);
});
});
},
deletedStudent({id}) {
//删除操作
return new Promise((resolve,reject)=>{
connection.query('delete from student where name=?',[id],(err,results)=>{
if (err) {
console.log(results);
console.log('出错了:' + err.message);
reject(false);
return false;
}
resolve(true);
})
});
}
};
const app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
app.listen(4000, () => console.log('Now browse to localhost:4000/graphql'));
4.查看演示结果
启动 node database.js
![《GraphQL 学习》](http://ddrvcn.oss-cn-hangzhou.aliyuncs.com/2019/9/BNzqU3.png)
![《GraphQL 学习》](http://ddrvcn.oss-cn-hangzhou.aliyuncs.com/2019/9/yim2qy.png)