koa2從搭建項(xiàng)目到實(shí)現(xiàn)API

koa2纺腊,以前沒(méi)有接觸過(guò),只知道是express的原班人馬開(kāi)發(fā)的誓沸,在一些方面優(yōu)于express拜隧,又經(jīng)歷了一次從koa到koa2的升級(jí)趁仙,應(yīng)該說(shuō)是比較成熟的了。
根據(jù)現(xiàn)在的技術(shù)實(shí)現(xiàn)方案薇组,現(xiàn)在大部分的web服務(wù)基本都是前后端分離模式的律胀,所以koa2的讓web應(yīng)用開(kāi)發(fā)和api的使用更加簡(jiǎn)便優(yōu)勢(shì)貌矿,更值得我們?nèi)W(xué)習(xí)逛漫。

本文只簡(jiǎn)單介紹將環(huán)境搭建起來(lái),可以讓初次學(xué)習(xí)koa或者web應(yīng)用的同學(xué)能夠更快的看到學(xué)習(xí)成果克握,增加學(xué)習(xí)的自信心枷踏,其中涉及到的很多的知識(shí)和技術(shù)點(diǎn)旭蠕,我們后續(xù)補(bǔ)充,不在本文做過(guò)多的闡述
本文的目的就是做知識(shí)的普及佑稠,文中可能會(huì)有些代碼是從網(wǎng)絡(luò)中復(fù)制的旗芬,但是都是親手調(diào)試可運(yùn)行疮丛,保證代碼的正常運(yùn)行的

搭建環(huán)境

  1. 安裝node
    這個(gè)不用想也不用考慮漱办,koa項(xiàng)目是基于node的娩井,上來(lái)什么都別說(shuō)似袁,先安裝node昙衅。但這里有個(gè)細(xì)節(jié)需要注意,node需要最低版本為7.6.0著瓶,主要是為了一些es6的語(yǔ)法支持材原。
brew install node

我這里是在mac環(huán)境上安裝的node季眷,由于本人習(xí)慣使用homebrew安裝子刮,如果不是mac環(huán)境的同學(xué),也可以直接到官網(wǎng)下載安裝包安裝葵孤。這個(gè)步驟比較簡(jiǎn)單橱赠,一般情況下看下官網(wǎng)的文檔介紹,可以直接搞定吓著。
node安裝完成后送挑,要查看下node的版本惕耕,有兩個(gè)目的诫肠,一是查看node是否安裝成功,再就是檢查是否滿足koa的版本需求谚殊。

node -v
npm -v

npm集成到node中了蛤铜,只要成功的安裝了node围肥,npm也會(huì)被成功安裝。

  1. 安裝koa
    我們學(xué)習(xí)和應(yīng)用的是koa項(xiàng)目置尔,就先安裝上koa吧榜轿。
    npm install koa --save
  2. 安裝koa2項(xiàng)目生成器并創(chuàng)建項(xiàng)目
npm install koa-generator -g
koa2 bbs

這里的koa-generator朵锣,并不是官方的項(xiàng)目生成器猪勇,而是狼叔-桑世龍為我們貢獻(xiàn)的財(cái)富,在這里助析,我們感謝狼叔外冀。
koa2 bbs掀泳,這行代碼創(chuàng)建了基于koa2的項(xiàng)目员舵,并生成基本的項(xiàng)目架構(gòu)∽矗基本的項(xiàng)目架構(gòu)如下:


koa2項(xiàng)目基本架構(gòu)圖
  1. 安裝依賴
    項(xiàng)目也創(chuàng)建完了措近,但是只是完成了一個(gè)基本的骨架瞭郑,還沒(méi)有血肉,接下來(lái)就需要安裝項(xiàng)目的依賴了
cd bbs
npm install

這個(gè)步驟可能消耗的時(shí)間有點(diǎn)長(zhǎng)擒权,這個(gè)和網(wǎng)絡(luò)環(huán)境有關(guān)菜拓,由于網(wǎng)絡(luò)的原因笛厦,還有可能某些依賴會(huì)安裝失敗裳凸,這個(gè)時(shí)候姨谷,我們可以通過(guò)修改npm鏡像來(lái)減少由于網(wǎng)絡(luò)環(huán)境導(dǎo)致安裝依賴失敗的問(wèn)題。
具體可參考淘寶NPM鏡像瞎颗。

  1. 啟動(dòng)服務(wù)
npm start

npm可以啟動(dòng)服務(wù)哼拔,但不支持熱更新瓣颅,我們這里只是測(cè)試項(xiàng)目能否正常啟動(dòng)宫补,執(zhí)行,熱更新的內(nèi)容健民,我們后續(xù)再講荞雏。
服務(wù)正常啟動(dòng)之后平酿,瀏覽器輸入:localhost:3000,如果頁(yè)面中展示了如"Hello Koa 2"的內(nèi)容蜈彼,說(shuō)明項(xiàng)目搭建成功。

搭建項(xiàng)目

這里的搭建項(xiàng)目棍辕,不是前面的使用koa2初始化一個(gè)項(xiàng)目楚昭,而是把前面通過(guò)koa2初始化的項(xiàng)目補(bǔ)充營(yíng)養(yǎng)抚太,讓它豐滿起來(lái)昔案。

  1. 安裝sequelize
    暫且不要關(guān)心sequelize是什么踏揣,以后會(huì)有專題細(xì)講,只需要了解一點(diǎn)就可以了:Sequelize是一個(gè)基于promise的nodejs ORM又谋,目前支持Postgres彰亥、mysql铃辖、SQLite和Microsoft SQL Server娇斩。它具有強(qiáng)大的事務(wù)支持犬第,關(guān)聯(lián)關(guān)系,讀取和復(fù)制等功能丰介。
npm install sequelize --save
  1. 安裝mysql哮幢、mysql2
    項(xiàng)目需要mysql的數(shù)據(jù)庫(kù)支持
npm install mysql mysql2 --save
  1. 配置Sequelize的數(shù)據(jù)庫(kù)鏈接
    在項(xiàng)目的根目錄下創(chuàng)建一個(gè)config目錄橙垢,config目錄中創(chuàng)建db.js,該文件主要用來(lái)創(chuàng)建mysql的數(shù)據(jù)庫(kù)鏈接的嗽元。
const Sequelize = require('sequelize');
const sequelize = new Sequelize('dbname','dbusername','password',{
    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'  //東八時(shí)區(qū)
});

module.exports = {
    sequelize
};

這些代碼可以直接使用剂癌,只需要將代碼中實(shí)例化Sequelie對(duì)象語(yǔ)句中的dbname更改為你的數(shù)據(jù)庫(kù)名佩谷,dbusername更改為你的數(shù)據(jù)庫(kù)用戶名琳要,passoword更改為你的數(shù)據(jù)庫(kù)密碼秤茅,其中數(shù)據(jù)庫(kù)名和數(shù)據(jù)庫(kù)用戶名不能為空框喳,密碼可以為空五垮,為空時(shí)則為空的字符串就可以了。

const sequelize = new Sequelize('bbs','root','',{
……
  1. 創(chuàng)建schema润绎、modules莉撇、controllers
    schema:數(shù)據(jù)表模型實(shí)例
    modules:實(shí)體模型
    controllers:控制器

    3個(gè)目錄下分別創(chuàng)建article.js棍郎。
    目錄結(jié)構(gòu)
  2. schema數(shù)據(jù)表模型
    在schema目錄下新建一個(gè)article.js文件涂佃,該文件的主要作用就是建立與數(shù)據(jù)表的對(duì)應(yīng)關(guān)系,也可以理解為代碼的建表汽抚。
    首先來(lái)分析表結(jié)構(gòu):
字段 說(shuō)明 是否必填
id 文章自增ID殊橙,主鍵 否,自動(dòng)填的
title 文章標(biāo)題
author 作者
content 文章內(nèi)容
category 文章分類

分析表結(jié)構(gòu)季研,主要是為了用來(lái)建表的誉察,表結(jié)構(gòu)持偏,是我們根據(jù)實(shí)體的關(guān)系抽象出來(lái)的實(shí)體關(guān)系鸿秆,根據(jù)這些關(guān)系建立表,將實(shí)體的關(guān)系存儲(chǔ)到表中卿叽。建表有兩種方式:一是使用mysql數(shù)據(jù)庫(kù)的命令行工具或者UI工具建表考婴,再就是使用我們前面介紹的Sequelize沥阱,讓程序去創(chuàng)建表。
使用mysql工具建表方式:

DROP TABLE IF EXISTS `article`;
CREATE TABLE `article` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  `author` varchar(255) NOT NULL,
  `content` varchar(255) NOT NULL,
  `category` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
SET FOREIGN_KEY_CHECKS = 1;

這是使用sql語(yǔ)句創(chuàng)建表的方式,我們看另一種借助Sequelize建表方式(Sequelize不光是能建表蛮寂,還能做數(shù)據(jù)庫(kù)的管理)易茬;
我們剛才在schema目錄下的article.js用來(lái)創(chuàng)建數(shù)據(jù)表模型的,也可以理解為創(chuàng)建一張數(shù)據(jù)表骄恶,代碼如下:

const moment = require("moment");
module.exports = function(sequelize,DataTypes){
    return sequelize.define('article',{
        id:{
            type: DataTypes.INTEGER,
            primaryKey: true,
            allowNull: true,
            autoIncrement: true
        },
        //文章標(biāo)題
        title:{
            type: DataTypes.STRING,
            allowNull: false,
            field: 'title'
        },
        //作者
        author:{
            type: DataTypes.STRING,
            allowNull: false,
            field: 'author'
        },
        //內(nèi)容
        content:{
            type: DataTypes.STRING,
            allowNull: false,
            field:'content'
        },
        //文章分類
        category:{
            type: DataTypes.STRING,
            allowNull: false,
            field: 'category'
        },
        // 創(chuàng)建時(shí)間
        createdAt:{
            type: DataTypes.DATE
        },
        // 更新時(shí)間
        updatedAt:{
            type: DataTypes.DATE
            }
        }
    },{
        /**
         * 如果為true僧鲁,則表示名稱和model相同寞秃,即user
         * 如果為fasle春寿,mysql創(chuàng)建的表名稱會(huì)是復(fù)數(shù)忽孽,即users
         * 如果指定的表名稱本身就是復(fù)數(shù)兄一,則形式不變
         */
        freezeTableName: true
    });
}
  1. 模型應(yīng)用出革、使用
    在項(xiàng)目中modules目錄下創(chuàng)建article.js文件蹋盆,為文章表,該文件為文章的實(shí)例楞抡。
// 引入mysql的配置文件
const db = require('../config/db');

// 引入sequelize對(duì)象
const Sequelize = db.sequelize;

// 引入數(shù)據(jù)表模型
const Article = Sequelize.import('../schema/article');
Article.sync({force: false}); //自動(dòng)創(chuàng)建表

class ArticleModel {
    /**
     * 創(chuàng)建文章模型
     * @param data
     * @returns {Promise<*>}
     */
    static async createArticle(data){
        return await Article.create({
            title: data.title, //標(biāo)題
            author: data.author,  //作者
            content: data.content,  //文章內(nèi)容
            category: data.category //文章分類
        });
    }

    /**
     * 查詢文章的詳情
     * @param id 文章ID
     * @returns {Promise<Model>}
     */
    static async getArticleDetail(id){
        return await Article.findOne({
            where:{
                id
            }
        });
    }
}

module.exports = ArticleModel;
  1. controller 控制器
    控制器的主要作用為功能的處理,項(xiàng)目中controller目錄下創(chuàng)建article.js竞慢,代碼如下:
const ArticleModel = require("../modules/article");

class articleController {
    /**
     * 創(chuàng)建文章
     * @param ctx
     * @returns {Promise.<void>}
     */
    static async create(ctx){
        //接收客服端
        let req = ctx.request.body;
        if(req.title && req.author && req.content && req.category){
            try{
                //創(chuàng)建文章模型
                const ret = await ArticleModel.createArticle(req);
                //使用剛剛創(chuàng)建的文章ID查詢文章詳情筹煮,且返回文章詳情信息
                const data = await ArticleModel.getArticleDetail(ret.id);

                ctx.response.status = 200;
                ctx.body = {
                    code: 200,
                    msg: '創(chuàng)建文章成功',
                    data
                }
            }catch(err){
                ctx.response.status = 412;
                ctx.body = {
                    code: 412,
                    msg: '創(chuàng)建文章失敗',
                    data: err
                }
            }
        }else {
            ctx.response.status = 416;
            ctx.body = {
                code: 200,
                msg: '參數(shù)不齊全'
            }
        }
    }

    /**
     * 獲取文章詳情
     * @param ctx
     * @returns {Promise.<void>}
     */
    static async detail(ctx){
        let id = ctx.params.id;
        if(id){
            try{
                // 查詢文章詳情模型
                let data = await ArticleModel.getArticleDetail(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 = articleController;
  1. 路由
    路由本冲,也可以簡(jiǎn)單理解為路徑劫扒,主要是作為請(qǐng)求的url沟饥,請(qǐng)求的路徑來(lái)處理一些請(qǐng)求贤旷,返回?cái)?shù)據(jù)。一般情況下性昭,基于node的項(xiàng)目,路由都是在一個(gè)叫做routes的目錄下面萧求。
const Router = require('koa-router');
const ArtileController = require('../controllers/article');

const router = new Router({
  prefix: '/api/v1'
});

/**
 * 文章接口
 */
//創(chuàng)建文章
router.post('/article/create',ArtileController.create);

//獲取文章詳情
router.get('/article/:id',ArtileController.detail)

module.exports = router
  1. 啟動(dòng)服務(wù)
    這里主要測(cè)試服務(wù)能否正常啟動(dòng)夸政,能否正常運(yùn)行榴徐。
npm start

如果啟動(dòng)過(guò)程中出現(xiàn)下面的結(jié)果坑资,說(shuō)明服務(wù)啟動(dòng)成功

?  bbs npm start

> bbs@0.1.0 start /usr/local/var/www/koa/bbs
> node bin/www

koa deprecated Support for generators will be removed in v3. See the documentation for examples of how to convert old middleware https://github.com/koajs/koa/blob/master/docs/migration.md app.js:20:5
Ignoring invalid configuration option passed to Connection: collate. This is currently a warning, but in future versions of MySQL2, an error will be thrown if you pass an invalid configuration options to a Connection
Ignoring invalid configuration option passed to Connection: collate. This is currently a warning, but in future versions of MySQL2, an error will be thrown if you pass an invalid configuration options to a Connection
Executing (default): CREATE TABLE IF NOT EXISTS `article` (`id` INTEGER auto_increment , `title` VARCHAR(255) NOT NULL, `author` VARCHAR(255) NOT NULL, `content` VARCHAR(255) NOT NULL, `category` VARCHAR(255) NOT NULL, `createdAt` DATETIME, `updatedAt` DATETIME, PRIMARY KEY (`id`)) ENGINE=InnoDB;
Executing (default): SHOW INDEX FROM `article`

接下來(lái)仿便,就可以測(cè)試接口了嗽仪。
我使用的測(cè)試接口工具為postman柒莉,以前postman好像是作為瀏覽器的一個(gè)插件存在的兢孝,現(xiàn)在不作為瀏覽器的插件了,直接做成了應(yīng)用了哨颂,可以直接從postmna官網(wǎng)下載相种。 官網(wǎng)地址https://www.getpostman.com/,然后我們根據(jù)我們的系統(tǒng)平臺(tái)來(lái)選擇合適的版本下載就可以了寝并。

  1. 解決跨域
    跨域是web開(kāi)發(fā)中不可避免的一個(gè)必須要解決的問(wèn)題了衬潦《频海跨域問(wèn)題,主要是要解決服務(wù)器端的通信問(wèn)題驾锰。在node的開(kāi)發(fā)中椭豫,只需要實(shí)現(xiàn)一個(gè)CORS標(biāo)準(zhǔn)就可以了赏酥。
npm install koa-cors --save

然后在根目錄下的app.js加入koa-cors的引用:

const cors = require('koa-cors')
app.use(cors()) //使用cors

然后重新啟動(dòng)服務(wù)裸扶。到這里為止低淡,還不能支持熱更新又固,現(xiàn)在主要測(cè)試功能猪杭,暫且先這么手動(dòng)重啟吧餐塘,后面會(huì)有專題描述熱更新服務(wù)。

  1. 測(cè)試接口
    前面我下載并且安裝好了postman皂吮,工具有了戒傻,代碼層面也準(zhǔn)備就緒税手,解決了跨域問(wèn)題,下面就可以測(cè)試接口是否可用了需纳。
    測(cè)試接口芦倒,我們先看下我們的路由管理文件routes目錄下的index.js文件。
//創(chuàng)建文章
router.post('/article/create',ArtileController.create);

//獲取文章詳情
router.get('/article/:id',ArtileController.detail)

這里有2個(gè)文章相關(guān)的接口兵扬,一個(gè)是創(chuàng)建新文章,一個(gè)是獲取文章詳情口蝠。我們先來(lái)測(cè)試創(chuàng)建新的文章器钟。
看路由,創(chuàng)建新文章需要的請(qǐng)求方式為post妙蔗,url為/article/create傲霸,那我們就根據(jù)這些信息使用postman進(jìn)行測(cè)試吧。


創(chuàng)建新文章

這是我創(chuàng)建新文章的接口測(cè)試眉反,然后看測(cè)試結(jié)果:


接口測(cè)試成功

運(yùn)行結(jié)果告訴我們創(chuàng)建新文章的接口已經(jīng)測(cè)試成功了昙啄,說(shuō)明這個(gè)接口可以走通了。如果我們現(xiàn)在是前后端分離的開(kāi)發(fā)模式禁漓,我們需要提供api的話跟衅,那么這個(gè)api就可以提供給前端同學(xué)使用了。
我們也可以從數(shù)據(jù)庫(kù)中驗(yàn)證一下執(zhí)行結(jié)果的正確性:
數(shù)據(jù)添加成功

數(shù)據(jù)也成功插入到數(shù)據(jù)庫(kù)中了播歼,我們也更加驗(yàn)證了我們接口的正確性和可執(zhí)行性了,這個(gè)接口到此結(jié)束掰读。
然后看下一個(gè)獲取文章詳情的接口秘狞。需要使用get的請(qǐng)求方式,請(qǐng)求的URL為/article/:id蹈集。


獲取文章詳情

成功獲取文章詳情

總結(jié)

到現(xiàn)在為止烁试,我們基本已經(jīng)完成了從0開(kāi)始搭建一個(gè)koa項(xiàng)目,并完成一些簡(jiǎn)單的api接口的實(shí)現(xiàn)拢肆,當(dāng)然了减响,只是最基本的實(shí)現(xiàn),里面還有很多可優(yōu)化的空間郭怪,對(duì)于一個(gè)作為入門案例來(lái)說(shuō)支示,已經(jīng)夠了。對(duì)于有深入了解或?qū)W習(xí)的朋友鄙才,希望我們功能學(xué)習(xí)颂鸿,共同提高。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末攒庵,一起剝皮案震驚了整個(gè)濱河市嘴纺,隨后出現(xiàn)的幾起案子败晴,更是在濱河造成了極大的恐慌,老刑警劉巖栽渴,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尖坤,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡闲擦,警方通過(guò)查閱死者的電腦和手機(jī)慢味,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)佛致,“玉大人贮缕,你說(shuō)我怎么就攤上這事“秤埽” “怎么了感昼?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)罐脊。 經(jīng)常有香客問(wèn)我定嗓,道長(zhǎng),這世上最難降的妖魔是什么萍桌? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任宵溅,我火速辦了婚禮,結(jié)果婚禮上上炎,老公的妹妹穿的比我還像新娘恃逻。我一直安慰自己,他們只是感情好藕施,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布寇损。 她就那樣靜靜地躺著,像睡著了一般裳食。 火紅的嫁衣襯著肌膚如雪矛市。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,158評(píng)論 1 308
  • 那天诲祸,我揣著相機(jī)與錄音浊吏,去河邊找鬼。 笑死救氯,一個(gè)胖子當(dāng)著我的面吹牛找田,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播径密,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼午阵,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起底桂,我...
    開(kāi)封第一講書(shū)人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤植袍,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后籽懦,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體于个,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年暮顺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了厅篓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡捶码,死狀恐怖羽氮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情惫恼,我是刑警寧澤档押,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布,位于F島的核電站祈纯,受9級(jí)特大地震影響令宿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜腕窥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一粒没、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧簇爆,春花似錦癞松、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至安寺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間首尼,已是汗流浹背挑庶。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留软能,地道東北人迎捺。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像查排,于是被迫代替她去往敵國(guó)和親凳枝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 原文鏈接:http://www.reibang.com/p/6b816c609669 前傳 出于興趣最近開(kāi)始研究k...
    懸筆e絕閱讀 7,220評(píng)論 1 11
  • 前傳 出于興趣最近開(kāi)始研究koa2,由于之前有過(guò)一些express經(jīng)驗(yàn)岖瑰,以為koa還是很好上手的叛买,但是用起來(lái)發(fā)現(xiàn)還...
    阿_希爸閱讀 119,614評(píng)論 81 240
  • 前傳 出于興趣最近開(kāi)始研究koa2,由于之前有過(guò)一些express經(jīng)驗(yàn)蹋订,以為koa還是很好上手的率挣,但是用起來(lái)發(fā)現(xiàn)還...
    little_short閱讀 18,762評(píng)論 4 17
  • 粗壯的樹(shù)根緊緊扎根于石壁上 壁上的青苔見(jiàn)證了這里的舊時(shí)光 時(shí)光流逝 歲月蹉跎 踏著青石板路 走進(jìn)這幽靜的公園里 一...
    曦陽(yáng)Z閱讀 391評(píng)論 0 0
  • 我在海邊撿到一個(gè)海螺,可不可以帶她回來(lái)露戒。 海螺是外表有一副堅(jiān)硬的軀殼椒功,可她的內(nèi)心卻是柔弱。當(dāng)潮水退去智什,海螺孤零零的...
    江北菜菜閱讀 494評(píng)論 0 1