RESTful 接口
REST 的全称是 REpresentational State Transfer,是一种 Web API 的设计风格
RESTful API 设计 6 大原则
一个 RESTful 风格的接口应该满足如下的 6 点原则:
- 统一接口:For example, the HTTP-based REST APIs make use of the standard HTTP methods (GET, POST, PUT, DELETE, etc.) and the URIs (Uniform Resource Identifiers) to identify resources
- 使用 client-server 架构解耦
- 无状态:server 不能保存与 client 的会话状态
- 可缓存的:响应数据应该声明自己能否被缓存
- 分层系统:采用反向代理服务器屏蔽 server 和 client
- 按需返回可执行代码:server 能够向 client 返回一段代码用以执行
RESTful API 最佳实践
- URL 中不要使用动词,动作交给 HTTP 的不同请求来区分
- 状态码必须准确,错误信息就要响应对应的错误状态码
下面使用 nodejs 编写了一个简单的 web 服务,提供了查询 user 的 RESTful get 接口:
var express = require('express');
var mysql = require("mysql");
var client = mysql.createConnection({host: '192.168.93.12',user: 'root',password: 'xxx',port: '3306',database: 'big_event',
});
client.connect();
var app = express();app.get("/user/:id", (req, res) => {let { id } = req.params;client.query(`select id, username, password, email from user where id=${id}`, (err, users) => {if (err) {console.warn(err);}if (users && users.length == 1) {res.send(users[0]);} else {res.send("wrong result");}});
})app.listen(5000, () => console.log('Now browse to localhost:5000/restful'));
对于上面的 API,使用 http://localhost:5000/user/1
即可获取到 id 为 1 的 user 信息
RESTfull API 的缺点
- 获取数据不够灵活:batch 获取数据时要发送多次请求。也容易过度获取数据:本来只需要2~3个值,结果返回了20个值
- 弱类型:js 的类型系统薄弱,除了 number、string、array、object 等,不支持自定义类型
针对这些缺点,提出了 GraphQL
GraphQL 接口
GraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时
用 GraphQL 将上面的查询接口重写如下:
const { graphqlHTTP } = require('express-graphql');
const { buildSchema } = require('graphql');// 定义 GraphQL schema
const schema = buildSchema(`type User {id: Intusername: Stringpassword: Stringemail: String}type Query {user(id: Int!): User}
`);// 定义 resolver 函数,用于处理查询
const root = {user: ({ id }) => {return new Promise((resolve, reject) => {client.query(`SELECT id, username, password, email FROM user WHERE id = ${id}`, (err, result) => {if (err) {reject(err);} else {resolve(result[0]);}});});}
};const app = express();app.use('/graphql', graphqlHTTP({schema: schema,rootValue: root,graphiql: true // 启用 GraphiQL 可视化工具
}));app.listen(5000, () => {console.log('GraphQL Server is running on http://localhost:5000/graphql');
});
启动后,我们在浏览器中能够访问到一个调试界面:
输入查询条件:
{user(id: 1) {idusernamepassword}
}
就可以得到查询结果:
{"data": {"user": {"id": 1,"username": "wangba","password": "124bd1296bec0d9d93c7b52a71ad8d5b"}}
}
GraphQL 的优点
- 前端变被动为主动,能够决定要获取哪些数据,不再依赖于和后端的 API 接口文档。前端能够专注于 UI 设计
- 增减字段很容易,易于扩展
- 批量获取数据只需要发送一次 HTTP 请求,节省了网络带宽
GraphQL 的缺点
- 缓存实现困难