Skip to content

03-nodeJS 中 Restful 架构实现

统计信息:字数 6348 阅读13分钟

1、什么是 restful

Restful:表述性状态转移(框架的原则和约束条件)主要用于客户端和服务器交互类的软件。基于这个风格设计的软件会更简洁,更有层次,实现缓存机制。这是一种URL的设计风格(路由风格)。

Restful:通俗的说,用什么样的方式写路由。常见的URL风格:静态 news/ids/1 利于SEO优化;动态 news?id=1 不利于SEO(后面的查询参数)原来是通过HTTP请求的内容判断具体的业务逻辑(增删改查)restful通过HTTP请求的类型(get post delete)判断业务逻辑。同一个资源使用同一个URL,具体操作根据请求的方法实现。

传统的URL http://127.0.0.1:user/delete/id 这样的URL中含有增删改查字样描述性的URL,和 HTTP 设计理念不符合。因为 HTTP 请求接口或者地址的时候完全没有必要去描述(HTTP本身没有语义)。

restful:面向资源(user)对于同一个资源,都在一个URL下操作,根据判断HTTP的请求的类型决定做不同的事情。HTTP 不同的请求类型(GET POST PUT DELETE)对应不同的数据库操作(增删改查)。

Node顶层路由:一个路由不一定对应一个界面(一个Html文件)http处理函数(路由风格)架构和业务层已经脱离关系了,架构是通用的解决方案。

2、原生实现 Restful

原生NodeJS实现服务

原生实现 Restful

npm install -D mysql body-parser
npm install co-mysql md5-node

Index.js

const http = require('http');
const mysql = require('mysql');
const co = require('co-mysql');
const md5 = require('md5-node');

let db = mysql.createPool({
  host: 'localhost',
  user: 'root',
  password: 'root',
  database: 'user',
});
let conn = co(db);

// 同一个URL下实现不同的操作
const app = http.createServer((req, res) => {
  if (req.method === "POST") {
    if (req.url === './user') {
      // res.end(JSON.stringify({
      //   message: 'POST操作',
      //   status: 200
      // }))
      let arr = [];
      req.on('data', (data) => {
        arr.push(data);
      })
      req.on('end', async () => {
        let buffer = Buffer.concat(arr);
        let { username, password } = JSON.parse(buffer.toString());
        let data = await conn.query(`select user from admin where user = '${username}'`);
        console.log(data);
        // 如果从数据库中检索到,返回已经注册
        if (data.length >= 1) {
          res.end(JSON.stringify({
            "statue": 200,
            "message": "用户名已经注册"
          }));
        } else {
          // 如果从数据库中没有检索到,直接写入数据库
          password = md5(password);
          let sql = `insert into admin (user,password) values ('${username}', '${password}')`;
          await conn.query(sql);
          res.end(JSON.stringify({
            'status': 200,
            'message': '注册成功'
          }));
        }
      });
    }
  } else if (req.method === "GET") {
    if (req.url === './user') {
      // res.end(JSON.stringify({
      //   message: 'GET操作',
      //   status: 200
      // }))
      let sql = 'select id, user, password from admin';
      let data = await conn.query(sql);
      res.end(JSON.stringify(data));
    }
  }
}).listen(3000);

REST client 配置 .http

@url = http://localhost:3000
@type = Content-Type: application/json

GET {{url}}/user HTTP/1.1

POST {{url}}/user HTTP/1.1
{{type}}

{
    "username": "admin",
    "password": 123456
}

3、框架实现 RestFul

express实现服务:改写了异步请求和回调函数,使用 generator 实现异步操作

Demo 01 Express 实现

使用 NodeJS 的 express 创建一个案例

npm init
npm install -D express
touch app.js
nodemon app.js
# nodemon 是自动更新的node(类似于热启动)

app.js

const express = require('express');
const app = express();

app.get('/user', (req, res) => {
  res.send('test page');
});

app.listen(3000);

URL 定位资源,HTTP描述操作

顶层路由设计:不需要有物理文件去映射路由

Demo02

Express 实现 restful

const express = require('express');
const http = require('http');
const mysql = require('mysql');
const co = require('co-mysql');
const md5 = require('md5-node');
const bodyparse = require('body-parser')

const app = express();

let db = mysql.createPool({
  host: 'localhost',
  user: 'admin',
  password: 'root',
  database: 'test-user',
});

let conn = co(db);

app.use(bodyparse.urlencoded({
  extended: true
}));

app.use(bodyparse.json());

app.post('/user', async (req, res) => {
  let { user, password } = req.body;
  let data = await conn.query(`select user from admin where user = '${username}'`);
    if (data.length >= 1) {
    res.send(JSON.stringify({
      'status': 200,
      'message': '用户名已经注册'
    }))
  } else {
    password = md5(password);
    let sql = `insert into admin (user,password) values ('${username}','${password}')`;
    await conn.query(sql);
    res.end(JSON.stringify({
      'status': 200,
      'message': '注册成功'
    }));
  }
});

app.get('/user/:id', (req, res) => {
  res.send(req.params.id);
  // 到数据库中查询(sql)
});

app.listen(3000);

demo03

koa 实现 restful

koa:async await

config.js

module.exports = {
  host: 'localhost',
  user: 'root',
  password: 'root',
  database: 'user',
};

Databases.js

const mysql = require('mysql');
const co = require('co-mysql');
const config = require('../config');

const { host, user, password, database } = config;
let db = mysql.createPool({
  host,
  user,
  password,
  database,
});

module.exports = co(db);

index.js

const Router = require('koa-router');
const md5 = require('md5-node');
const router = new Router();

router.get('/user', async ctx => {
  ctx.body = 'main page';
});

app.js

const Koa = require('koa');
const Router = require('koa-router');
const body = require('koa-bodyparser');

const app = new Koa();
const router = new Router();
app.context.db = require('./libs/databases');
app.context.config = config;

app.use(body());
router.user('/api', require('./router'));

app.use(router.routes());
app.listen(3000);

Last update: November 9, 2024