Node.js 实现RestFul API

前端开发人员,有时候需要做一些接口调试,koa2+mysql2的组合方式恰好能够快速实现,作为学习笔记记录下

环境准备

首先需要node.js和mysql,mac可使用homebrew快速安装

搭建koa2项目

可以命令一步一步搭建

npm init

这里我们使用koa-generator生成项目,类似vue-cli

### 全局安装 koa-generator
npm install koa-generator -g

### 创建项目,demo为项目名
koa2 demo

### 进入项目目录
cd demo 

### 安装项目依赖
npm install 

### 启动项目 可任选一种
npm start   (每次代码修改都需要重启项目)
npm run dev (代码发生改变时自动重启项目)

生成的项目目录结构如下,可以看到package.json中已给我们添加了很多插件依赖


启动项目完成后,在浏览器输入:localhost:3000,浏览器运行结果,搭建的koa2项目就已完成

实现API

安装依赖

这里选择Node的ORM框架Sequelize来操作数据库。这样,我们读写的都是JavaScript对象,Sequelize帮我们把对象变成数据库中的行,同时安装mysql2。

npm install sequelize mysql2 --save

数据库连接

在根目录下新建config目录->新建db.js文件

const Sequelize = require('sequelize');
/**
 * 数据库名称, 账号,密码
 */
const sequelize = new Sequelize('zf','root','123456',{
    host:'localhost',
    dialect:'mysql',
    operatorsAliases:false,
    dialectOptions:{
        //字符集
        charset:'utf8mb4',
        collate:'utf8mb4_unicode_ci',
        supportBigNumbers: true,
        bigNumberStrings: true
    },
    pool:{
        max: 5,
        min: 0,
        acquire: 30000,
        idle: 10000
    },
    timezone: '+08:00'  //东八时区
});
 
module.exports = {
    sequelize
};

定义数据模型

在根目录下新建models目录->新建pet.js文件

const moment = require('moment');
module.exports = function(sequelize,DataTypes){
    return sequelize.define('pet',
        {
            id:{
                type: DataTypes.INTEGER(11),
                primaryKey: true,
                allowNull: false,
                autoIncrement: true
            },
            name:{
                type: DataTypes.STRING(100),
                allowNull: false,
                field: 'name'
            },
            gender:{
                type: DataTypes.TINYINT(0),
                allowNull: false,
                field: 'gender'
            },
            birth:{
                type: DataTypes.DATE,
                allowNull: false,
                field: 'birth',
                set: function(val) {
                    this.setDataValue('birth', new Date(val*1000));
                },
                get() {
                    return moment(this.getDataValue('birth')).format('YYYY-MM-DD HH:mm:ss');
                }
            },
            isDeleted: {
              type: DataTypes.BOOLEAN,
              allowNull: true,
              defaultValue: false
            },
            createdAt: {
                type: DataTypes.DATE,
                allowNull: true,
                get() {
                    return moment(this.getDataValue('createdAt')).format('YYYY-MM-DD HH:mm:ss');
                }
            },
            updatedAt: {
                type: DataTypes.DATE,
                allowNull: true,
                get() {
                    return moment(this.getDataValue('updatedAt')).format('YYYY-MM-DD HH:mm:ss');
                }
            },
            version: {
                type: DataTypes.BIGINT,
                allowNull: true,
            }
        },
        {   
            /**
             * 如果为true,则表示名称和model相同,即user
             * 如果为fasle,mysql创建的表名称会是复数,即users
             * 如果指定的表名称本身就是复数,则形式不变
             */
            freezeTableName: true,

            //关闭Sequelize的自动添加timestamp的功能
            timestamps: false
        }
    );
}

模型操作

在根目录下新建modules目录->新建pet.js文件

//引入db配置
const db = require('../config/db')

//引入sequelize对象
const Sequelize = db.sequelize

//引入数据表模型
const pet = Sequelize.import('../models/pet')
//自动创建表
pet.sync({ force: false }); 

//数据库操作类
class petModel {

    static async createPet(data) {
        var now = Date.now();
        return await pet.create({
            name: data.name,
            gender: data.gender,
            birth: data.birth,
            createdAt: now,
            updatedAt: now,
            version: 0
        })
    }

    static async getPets() {
        return await pet.findAll({
            where: {
            }
        })
    }

    static async getPet(id) {
        console.log(id)
        return await pet.findOne({
            where: {
                id
            }
        })
    }
}

module.exports = petModel;

逻辑操作

在根目录下新建controllers目录->新建pet.js文件

const petModel = require("../modules/pet");
 
class petController {
    /**
     * 创建宠物信息
     * @param ctx
     * @returns {Promise.<void>}
     */
    static async create(ctx){
        //接收客服端
        let req = ctx.request.body;
        if(req.name && req.gender && req.birth ){
            try{
                //创建宠物信息模型
                const ret = await petModel.createPet(req);
                const data = await petModel.getPet(ret.id);
 
                ctx.response.status = 200;
                ctx.body = {
                    code: 200,
                    msg: '创建宠物信息成功',
                    data
                }
            }catch(err){
                console.log(err)
                ctx.response.status = 412;
                ctx.body = {
                    code: 412,
                    msg: '创建宠物信息失败',
                    data: err
                }
            }
        }else {
            ctx.response.status = 416;
            ctx.body = {
                code: 200,
                msg: '参数不齐全'
            }
        }
    }
 
    /**
     * 获取宠物详情
     * @param ctx
     * @returns {Promise.<void>}
     */
    static async detail(ctx){
        let id = ctx.request.query.id;
        if(id){
            try{
                let data = await petModel.getPet(id);
                ctx.response.status = 200;
                ctx.body = {
                    code: 200,
                    msg: '查询成功',
                    data
                }
            }catch(err){
                ctx.response.status = 412;
                ctx.body = {
                    code: 412,
                    msg: '查询失败',
                    data
                }
            }
        }else {
            ctx.response.status = 416;
            ctx.body = {
                code: 416,
                msg: '宠物ID必须传'
            }
        }
    }
}

module.exports = petController;

路由设置

在routes目录下新建pet.js文件

const router = require('koa-router')()

const PetController = require('../controllers/pet');
 
router.prefix('/pet')

router.post('/create',PetController.create);

router.get('/get',PetController.detail)
 
module.exports = router

然后再App.js中添加以下内容

const pet = require('./routes/pet')
app.use(pet.routes(), pet.allowedMethods())

最后的项目目录结构如下:

启动项目服务

npm run dev

这时候会发现报如下错误:

到这里,看gitHub上的提示是新版本不支持这种引入方式,请参考最新的demo

这里把sequelize的版本降低下来引入

npm install sequelize@^5.x.x --save

再 npm run dev,可以看到能正常运行起来了

测试API

用postman调用刚刚新建的接口

查看数据库

简单的接口实现已完成

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351