API 接口设计原则:RESTful 与 GraphQL

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 的缺点

  • 缓存实现困难
相关推荐
许野平30 分钟前
Rust: 利用 chrono 库实现日期和字符串互相转换
开发语言·后端·rust·字符串·转换·日期·chrono
齐 飞2 小时前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
暮毅2 小时前
10.Node.js连接MongoDb
数据库·mongodb·node.js
LunarCod2 小时前
WorkFlow源码剖析——Communicator之TCPServer(中)
后端·workflow·c/c++·网络框架·源码剖析·高性能高并发
码农派大星。3 小时前
Spring Boot 配置文件
java·spring boot·后端
杜杜的man4 小时前
【go从零单排】go中的结构体struct和method
开发语言·后端·golang
幼儿园老大*4 小时前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go
llllinuuu4 小时前
Go语言结构体、方法与接口
开发语言·后端·golang
cookies_s_s4 小时前
Golang--协程和管道
开发语言·后端·golang
为什么这亚子4 小时前
九、Go语言快速入门之map
运维·开发语言·后端·算法·云原生·golang·云计算