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

  • 缓存实现困难
相关推荐
金銀銅鐵3 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(上)
java·后端·ai编程
念何架构之路4 小时前
go-grpc设计思想
开发语言·后端·golang
system_error_x5 小时前
SpringBoot 集成 Thymeleaf 简洁入门
java·spring boot·后端
步行cgn6 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
码事漫谈7 小时前
AI 读你的提示词,其实很没耐心
后端
用户8356290780518 小时前
如何使用 Python 格式化 Excel 单元格中的长文本
后端·python
我命由我123458 小时前
Python 开发 - Python 的 pathlib
java·开发语言·后端·python·学习·java-ee·学习方法
IT_陈寒8 小时前
Java性能优化完全指南
前端·人工智能·后端
电子IT笔记8 小时前
对接群晖NAS,上传和删除踩坑记录
前端·后端
Mk598788 小时前
P4:把 Agent 的记忆搬进 Redis —— AgentScope-Java 工程化实战
后端