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

  • 缓存实现困难
相关推荐
long3162 分钟前
Aho-Corasick 模式搜索算法
java·数据结构·spring boot·后端·算法·排序算法
rannn_11129 分钟前
【苍穹外卖|Day4】套餐页面开发(新增套餐、分页查询、删除套餐、修改套餐、起售停售)
java·spring boot·后端·学习
短剑重铸之日39 分钟前
《设计模式》第十一篇:总结
java·后端·设计模式·总结
Dragon Wu2 小时前
Spring Security Oauth2.1 授权码模式实现前后端分离的方案
java·spring boot·后端·spring cloud·springboot·springcloud
一个有梦有戏的人2 小时前
Python3基础:进阶基础,筑牢编程底层能力
后端·python
爬山算法2 小时前
Hibernate(88)如何在负载测试中使用Hibernate?
java·后端·hibernate
独断万古他化3 小时前
【Spring 原理】Bean 的作用域与生命周期
java·后端·spring
我爱加班、、3 小时前
Websocket能携带token过去后端吗
前端·后端·websocket
一 乐3 小时前
校园二手交易|基于springboot + vue校园二手交易系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端
80530单词突击赢3 小时前
SpringBoot整合SpringMVC全解析
java·spring boot·后端