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 接口:
javascript
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 将上面的查询接口重写如下:
javascript
const { graphqlHTTP } = require('express-graphql');
const { buildSchema } = require('graphql');
// 定义 GraphQL schema
const schema = buildSchema(`
type User {
id: Int
username: String
password: String
email: 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');
});
启动后,我们在浏览器中能够访问到一个调试界面:
输入查询条件:
javascript
{
user(id: 1) {
id
username
password
}
}
就可以得到查询结果:
javascript
{
"data": {
"user": {
"id": 1,
"username": "wangba",
"password": "124bd1296bec0d9d93c7b52a71ad8d5b"
}
}
}
GraphQL 的优点
- 前端变被动为主动,能够决定要获取哪些数据,不再依赖于和后端的 API 接口文档。前端能够专注于 UI 设计
- 增减字段很容易,易于扩展
- 批量获取数据只需要发送一次 HTTP 请求,节省了网络带宽
GraphQL 的缺点
- 缓存实现困难