自学内容网 自学内容网

【express-generator】-06 RESTful API设计(第二阶段)

前言:

前面我们学习了第一阶段的express-generator内容以及做了对应练习,现在我们正式开始第二阶段的学习以及练习。本篇介绍的内容是RESTful API设计。

第二阶段的大纲如下: 

  1. RESTful API 设计

    • 学习如何设计符合 REST 原则的 API,包括资源的表示和 HTTP 方法的使用。
  2. 路由分组

    • 学习如何使用路由分组来组织相关的路由,提高代码的可维护性。
  3. 路由重定向

    • 学习如何使用 res.redirect() 和 res.location() 来实现路由重定向。
  4. CRUD 操作

    • 练习实现完整的 CRUD 操作的路由,包括与数据库的交互。

 这一篇介绍的是RESTful API 设计。

一、RESTful 原则

1.核心概念:

  1. 无状态(Stateless)

    • 每个请求从客户端到服务器都包含所有必要的信息来理解和处理请求。服务器不会存储任何客户端请求之间的状态信息。

  2. 统一接口(Uniform Interface)

    • 通过统一的接口与资源进行交互,使得资源能够被独立地操作。资源通过 URI(统一资源标识符)进行识别,操作通过 HTTP 方法(GET、POST、PUT、DELETE 等)进行。

  3. 资源导向(Resource-Oriented)

    • API 的设计围绕资源展开,每个资源都有一个唯一的 URI。资源可以是实体(如用户、文章、评论)或其他任何可以被命名的事物。

  4. 超媒体作为应用状态的引擎(HATEOAS)

    • 客户端通过服务器提供的超媒体链接动态发现可用的动作和资源,而不是硬编码在客户端中。

  5. 分层系统(Layered System)

    • 系统可以由多个分层组成,每个分层都有不同的功能。客户端通常不知道它们是直接与服务器通信,还是与中间层(如代理、网关)通信。

2.作用

  1. 可扩展性

    • 由于无状态和分层系统的设计,RESTful API 可以轻松扩展,支持大量客户端和分布式部署。

  2. 互操作性

    • 使用标准的 HTTP 方法和 URI,使得不同语言和平台的客户端都可以与 API 交互。

  3. 简单性和一致性

    • 统一接口和资源导向的设计使得 API 更容易理解和使用。

  4. 可维护性

    • 由于 API 的设计基于资源和标准方法,代码更容易维护和扩展。

 二、如何设计 RESTful API

1. 定义资源

  • 确定你的应用程序中的资源(如用户、文章、评论等)。

  • 每个资源都有一个唯一的 URI。

2. 设计 URI

  • 使用有意义的 URI 来表示资源。例如:

    • /users 表示用户集合。

    • /users/1 表示 ID 为 1 的用户。

3. 使用 HTTP 方法

  • 使用标准的 HTTP 方法来操作资源:

    • GET:获取资源。

    • POST:创建新资源。

    • PUT:更新现有资源。

    • DELETE:删除资源。

4. 返回状态码和响应体

  • 使用适当的 HTTP 状态码来表示请求的结果(如 200 OK、201 Created、404 Not Found、400 Bad Request 等)。

  • 返回有意义的响应体,通常为 JSON 格式。

 三、示例练习

1.示例设计

假设我们有一个简单的用户管理系统,包含以下资源和操作:

资源:

  • 用户(/restful_users

操作:

  • 获取所有用户(GET /restful_users

  • 获取单个用户(GET /restful_users/:id

  • 创建新用户(POST /restful_users

  • 更新用户信息(PUT /restful_users/:id

  • 删除用户(DELETE /restful_users/:id

2.示例 API 设计

  1. 获取所有用户

    • URIGET /restful_users

    • 响应:返回用户列表的 JSON。

  2. 获取单个用户

    • URIGET /restful_users/:id

    • 响应:返回指定用户的 JSON。

  3. 创建新用户

    • URIPOST /restful_users

    • 请求体:包含用户信息的 JSON。

    • 响应:返回新创建的用户信息和状态码 201。

  4. 更新用户信息

    • URIPUT /restful_users/:id

    • 请求体:包含更新信息的 JSON。

    • 响应:返回更新后的用户信息。

  5. 删除用户

    • URIDELETE /restful_users/:id

    • 响应:返回状态码 204(无内容)。

 3.示例代码(跟篇练习)

3.1 创建express应用

使用express-generator脚手架创建一个express应用程序。

//安装express-generator,如已经安装则跳过。
npm install -g express-generator
//创建express应用程序,然后跟着提示往下走。
express xx
cd xx
npm install

3.2 创建模拟数据

在项目根目录下创建一个 data.json 文件,用于存储用户数据:

[
  { "id": 1, "name": "Alice", "email": "alice@example.com" },
  { "id": 2, "name": "Bob", "email": "bob@example.com" },
  { "id": 3, "name": "Tom", "email": "tom@example.com" }
]

3.3 创建工具函数

utils/tool.js 中,添加工具函数用于读取和写入数据文件,以及处理结果响应:

// utils/tool.js
const fs = require('fs');
const path = require('path');

const dataFilePath = path.join(__dirname, '../data.json');

// 读取数据
function readData() {
  const data = fs.readFileSync(dataFilePath, 'utf8');
  return JSON.parse(data);
}

// 写入数据
function writeData(data) {
  fs.writeFileSync(dataFilePath, JSON.stringify(data, null, 2));
}

// 成功响应
function successResponse(res, data, status = 200) {
  res.status(status).json({
    success: true,
    data,
    status
  });
}

// 错误响应
function errorResponse(res, message, status = 400) {
  res.status(status).json({
    success: false,
    message,
    status
  });
}

module.exports = {
  readData,
  writeData,
  successResponse,
  errorResponse,
};

3.4 路由方法

routes 文件夹下创建一个 restful_user.js 文件,用于定义用户相关的路由:

// routes/restful_user.js
const express = require('express');
const router = express.Router();
const { readData, writeData, successResponse, errorResponse } = require('../utils/tool');

// 获取所有用户
router.get('/', (req, res) => {
  const users = readData();
  successResponse(res, users);
});

// 获取单个用户
router.get('/:id', (req, res) => {
  const users = readData();
  const user = users.find((u) => u.id === parseInt(req.params.id));
  if (!user) {
    errorResponse(res, 'User not found', 404);
  } else {
    successResponse(res, user);
  }
});

// 创建新用户
router.post('/', (req, res) => {
  const { name, email } = req.body;
  if (!name || !email) {
    errorResponse(res, 'Invalid user data', 400);
  } else {
    const users = readData();
    const newUser = {
      id: users.length + 1,
      name,
      email,
    };
    users.push(newUser);
    writeData(users);
    successResponse(res, newUser, 201);
  }
});

// 更新用户信息
router.put('/:id', (req, res) => {
  const users = readData();
  const userIndex = users.findIndex((u) => u.id === parseInt(req.params.id));
  if (userIndex === -1) {
    errorResponse(res, 'User not found', 404);
  } else {
    const { name, email } = req.body;
    if (name) users[userIndex].name = name;
    if (email) users[userIndex].email = email;
    writeData(users);
    successResponse(res, users[userIndex]);
  }
});

// 删除用户
router.delete('/:id', (req, res) => {
  const users = readData();
  const userIndex = users.findIndex((u) => u.id === parseInt(req.params.id));
  if (userIndex === -1) {
    errorResponse(res, 'User not found', 404);
  } else {
    const deletedUser = users.splice(userIndex, 1)[0];
    writeData(users);
    successResponse(res, deletedUser, 204);
  }
});

module.exports = router;

3.5 引入和使用

app.js 中引入 restful_user.js 路由模块,并将其挂载到/restful_user路径下

3.6 API测试

 我在bin/www中修改了端口号

以及添加了一条服务器启动的打印语句

(1)启动服务器:nodemon npm start
(2)打开apipost工具
-1 获取所有用户
  • URIGET /restful_users

  • 响应:返回用户列表的 JSON。

-2 获取单个用户
  • URIGET /restful_users/:id

  • 响应:返回指定用户的 JSON。

-3 添加用户数据
  • URIPOST /restful_users

  • 请求体:包含用户信息的 JSON。

  • 响应:返回新创建的用户信息和状态码 201。

我们可以在data.json中看到新增的用户数据

-4 修改用户数据
  • URIPUT /restful_users/:id

  • 请求体:包含更新信息的 JSON。

  • 响应:返回更新后的用户信息。

 这里我们将新增加的用户数据(id为4),将name从“张三”改为“张三四五”

data.json中的数据页也会对应修改。 

 

假设我们修改的是不存在的id数据,(此时data.json只有四条数据)响应结果则如下:

-5 删除用户数据
  • URIDELETE /restful_users/:id

  • 响应:返回状态码 204(无内容)。

 

 此时id为1的用户数据已被删除。

 如果我们对不存在的id数据进行删除,响应结果如下:


原文地址:https://blog.csdn.net/orbit4/article/details/145263325

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!