接口設計

1、接口設計規範:RESTful

①參考文檔:理解RESTful架構RESTful API 設計指南
html

HTTP協議裏面,四個表示操做方式的動詞:GET、POST、PUT、DELETE。它們分別對應四種基本操做:GET用來獲取資源,POST用來新建資源(也能夠用於更新資源),PUT用來更新資源,DELETE用來刪除資源mysql

③具體:web

  • GET(SELECT):從服務器取出資源(一項或多項)。sql

  • POST(CREATE):在服務器新建一個資源。數據庫

  • PUT(UPDATE):在服務器更新資源(客戶端提供改變後的完整資源)。express

  • PATCH(UPDATE):在服務器更新資源(客戶端提供改變的屬性)。json

  • DELETE(DELETE):從服務器刪除資源。api

  • HEAD:獲取資源的元數據。數組

  • OPTIONS:獲取信息,關於資源的哪些屬性是客戶端能夠改變的。promise

2、案例(基於RESTful接口設計規範來設計接口)

①把SQL語句導入MySQL數據庫,生成數據表

--Community management website

CREATE DATABASE IF NOT EXISTS cms;

use cms;

-- 用戶表
CREATE TABLE users(
    id INT PRIMARY  KEY auto_increment,
    username VARCHAR(50) NOT NULL, -- 用戶名
    password VARCHAR(50) NOT NULL, -- 密碼
    email VARCHAR(50) NOT NULL, -- 郵箱
    avater VARCHAR(100) NULL, -- 頭像
    gender bit NULL, --性別
    create_time DATETIME NOT NULL, -- 建立時間
    modify_time DATETIME NOT NULL, -- 修改時間
    nickname VARCHAR(50) NOT NULL -- 暱稱
);

-- 話題表
CREATE TABLE topics(
    id INT PRIMARY KEY auto_increment, 
    title VARCHAR(100) NOT NULL, -- 文章標題
    content TEXT NOT NULL, -- 文字內容
    user_id INT NOT NULL,  -- 所屬用戶
    create_time DATETIME NOT NULL, -- 發佈時間
    modify_time DATETIME NOT NULL -- 修改時間
); 

-- 評論表
CREATE TABLE comments(
    id INT PRIMARY KEY auto_increment,
    content TEXT NOT NULL, -- 評論內容
    create_time DATETIME NOT NULL, -- 評論時間
    modify_time DATETIME NOT NULL,
    article_id INT NOT NULL, -- 所屬文章
    user_id INT NOT NULL, -- 所屬用戶
    reply_id INT NULL -- 所屬回覆人
);

②建立目錄結構

③設計路由,編寫路由代碼,編寫控制器函數 router.js

const express = require('express');
const router = express.Router() ;
const userController = require('./controllers/user');
const topicsController = require('./controllers/topic');
const commentController = require('./controllers/comment');
const sessionController = require('./controllers/session');

//用戶資源
router
    .get('/users',userController.list)
    .post('/users',userController.create)
    .patch('/users/:id',userController.update)
    .delete('/users/:id',userController.destroy)    
//話題資源
router
    .get('/topics',topicsController.list)
    .post('/topics',topicsController.create)
    .patch('/topics/:id',topicsController.update)
    .delete('/topics/:id',topicsController.destroy)

//評論資源
router
    .get('/comments',commentController.list)
    .post('/comments',commentController.create)
    .patch('/comments/:id',commentController.update)
    .delete('/comments/:id',commentController.destroy)

//會話資源
router
    .get('/session',sessionController.get)
    .post('/session',sessionController.create)
    .delete('/session/:id',sessionController.destroy)

//導出router (重要)
module.exports = router;

④封裝 Promise版本的db.query方法 db.js

const mysql = require('mysql');
// 使用鏈接池:效率更高,不須要每次操做數據庫都要三步走
const pool =mysql.createPool({
    host:'localhost',
    user:'root',
    password:'123456',
    database:'cms'
});
exports.query = function(sqlStr){
    // 從鏈接池從拿一個鏈接,使用promise的方法
    return new Promise((resolve,reject) =>{
        pool.getConnection((err,connection) => {
            if(err){
                return reject(err)
            }
            connection.query(sqlStr,(err,...args) => {
                // 操做完鏈接,儘早釋放鏈接 
                connection.release()
                if(err){
                    return reject(err)
                }
                resolve(...args)
            })
        })
    })
}

⑤用戶管理:建立用戶 user.js

const md5 = require('blueimp-md5');
const moment = require('moment');
const db = require('../models/db');


exports.list = (req,res,next) => {
    //待完成
};
exports.create = async (req,res,next) => {
    const body=req.body;
    const sqlStr=`
    INSERT INTO users(username,password,email,avater,gender,create_time,modify_time,nickname)
    VALUES(
        '${body.email}',
        '${md5(md5(body.password))}',
        '${body.email}',
        'default-avater.png',
        0,
        '${moment().format('YYYY-MM-DD hh:mm:ss')}',
        '${moment().format('YYYY-MM-DD hh:mm:ss')}',
        '${body.nickname}'
    )`;
    // 利用try-catch捕獲異常:try中的代碼一旦出錯,當即進入catch代碼塊
    try{
        const ret = await db.query(sqlStr)
        const users = await db.query(`SELECT * FROM users WHERE id='${ret.insertId}'`)
        body.id = ret.insertId
        res.status(201).json(users[0])
    }catch(err){
        res.status(500).json({
            error:err.message
        })
    }
};
exports.update = (req,res,next) => {
    // 待完成
};
exports.destroy = (req,res,next) => {
    // 待完成
};

⑥會話管理:建立會話,獲取會話信息,銷燬會話 session.js

const md5 = require('blueimp-md5')
const db = require('../models/db')

// 獲取登錄狀態
exports.get = (req,res,next) => {
    const {user} = req.session
    if(!req.session.user){
        return res.status(401).json({
            error: 'Unauthorized'
        })
    }
    res.status(200).json(user)
}
// 建立登錄狀態
exports.create = async (req,res,next) => {
    try{
        // 接收表單數據
        const body=req.body
        body.password = md5(md5(body.password))
        // 處理數據庫登錄請求
        const sqlStr=`
            SELECT * FROM users WHERE email='${body.email}' and password='${body.password}'`
        const [user] = await db.query(sqlStr)
        // 發送響應
        if(!user){
            return res.status(404).json({
                error:'Invalid email or password!'
            })
        }
        req.session.user = user
        res.status(201).json(user)
    }catch(err){
        next(err)
    }
}
// 刪除登錄狀態
exports.destroy = (req,res,next) => {
    delete req.session.user
    res.status(201).json({})
}

⑦話題管理:建立話題,話題分頁列表,刪除話題,更新話題 topic.js

const moment = require('moment')
const db = require('../models/db')  

// 分頁查詢獲取全部話題
exports.list = async(req, res, next) => {
    let {_page=1,_limit=20} =req.query //req.query用於獲取get請求url ? 後面的參數
    if(_page < 1){_page = 1}
    if(_limit < 1){ _limit = 1}
    if(_limit > 20){_limit = 20}
    const start = (_page-1)*_limit
    try {
        /* 
        第1頁  0 20
        第2頁  20 20 
        第3頁  40 20
        第n頁  (_page-1)*_limit _limit  
        */
        const sqlStr = `SELECT * FROM topics LIMIT ${start},${_limit}`
        const topics = await db.query(sqlStr)
        res.status(200).json(topics)
    } catch (error) {
        next(error)
    }
}
// 建立話題
exports.create = async (req, res, next) => {
    try{
        // 登錄校驗
        const {user} = req.session
        if(!user){
            return res.status(401).json({
                error:'Unauthorized'
            })
        }
        const body = req.body
        body.create_time = moment().format('YYYY-MM-DD hh:mm:ss')
        body.modify_time = moment().format('YYYY-MM-DD hh:mm:ss')
        body.user_id = user.id
        const sqlStr = `
            INSERT INTO topics(title,content,user_id,create_time,modify_time)
            VALUES('${body.title}','${body.content}','${body.user_id}','${body.create_time}','${body.modify_time}')`
        // 注意:query方法查詢返回的是一個數組,增刪改返回的是對象
        const ret = await db.query(sqlStr)
        const [topic] = await db.query(`SELECT * FROM topics WHERE id=${ret.insertId}`)
        res.status(201).json(topic)
    }catch(error){
        next(error)
    }
}
// 更新話題
exports.update = async (req, res, next) => {
    try {
        // 登錄校驗
        const {user} = req.session
        if(!user){
            return res.status(401).json({
                error:'Unauthorized'
            })
        }
        // id一致校驗
        const {id} = req.params
        const [topic] = await db.query(`SELECT * FROM topics WHERE id=${id}`)
        if(!topic){
            return res,status(404).json({
                error: 'this Topic Not Found'
            })
        }
        if(topic.user_id !== req.session.user.id){
            return res.status(400).json({
                error: 'dupdate Invalid'
            })
        }
        const body = req.body
        const sqlStr = `
            UPDATE topics SET title='${body.title}',content='${body.content}',modify_time='${moment().format('YYYY-MM-DD hh:mm:ss')}'
            WHERE id=${id}
        `
        await db.query(sqlStr)
        const [updatedTopic] = await db.query(`SELECT * FROM topics WHERE id=${id}`)
        res.status(201).json(updatedTopic)
    } catch (error) {
        next(error)
    }
}
// 刪除話題
exports.destroy = async (req, res, next) => {
    try {
        // 登錄校驗
        const {user} = req.session
        if(!user){
            return res.status(401).json({
                error:'Unauthorized'
            })
        }
        // url 中的:id叫作動態路由參數,
        //總結:查詢字符串req.query,post請求體req.body,動態路由參數req.params
        const {id} = req.params
        // 判斷話題是否存在或者話題的ID是否和刪除話題的ID一致
        const [topic] = await db.query(`SELECT * FROM topics WHERE id=${id}`)
        if(!topic){
            return res,status(404).json({
                error: 'this Topic Not Found'
            })
        }
        if(topic.user_id !== req.session.user.id){
            return res.status(400).json({
                error: 'DELETE Invalid'
            })
        }
        const sqlStr = `DELETE FROM topics WHERE id=${id}`
        await db.query(sqlStr)
        res.status(201).json({})
    } catch (error) {
        next(error)
    }
}

⑧評論管理:建立評論

const db = require('../models/db')
const moment = require('moment')

exports.list = (req,res,next) => {
    // 待補
}
exports.create = async (req,res,next) => {
    try {
        // 登錄校驗
        const {user} = req.session
        if(!user){
            return res.status(401).json({
                error:'Unauthorized'
            })
        }
        // 獲取表單數據-->操做數據庫-->發送響應數據
        const body = req.body
        body.create_time = moment().format('YYYY-MM-DD hh:mm:ss')
        body.modify_time = moment().format('YYYY-MM-DD hh:mm:ss')
        const sqlStr = `
        INSERT INTO comments(content,create_time,modify_time,article_id,user_id)
        VALUES(
            '${body.content}',
            '${body.create_time}',
            '${body.modify_time}',
            '${body.article_id}',
            '${req.session.user.id}'
        )`
        const {insertId} = await db.query(sqlStr)
        const [comment] = await db.query(`SELECT *FROM comments WHERE id=${insertId}`)
        res.status(201).json(comment)
    } catch (error) {
        next(error)
    }
}
exports.update = (req,res,next) => {
    // 待補
}
exports.destroy = (req,res,next) => {
    // 待補
}

⑨啓動文件 app.js

const express = require('express');
const router = require('./router');
const bodyParser = require('body-parser');
const session = require('express-session')

const app=express();

// 配置body-parser
app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());

// 配置使用express-session
app.use(session({
    secret:'loaduser',
    resave:false,
    saveUninitialized:false
}));

// 把路由應用到app中
app.use(router);

app.listen(3000,() => {
    console.log('App is running at port 3000, please visit http://127.0.0.1:3000/')
});

⑩使用postman配合MySQL數據庫進行接口調試

項目未完成....

相關文章
相關標籤/搜索