koa2+mongoose,接口開發實戰第一槍

初始化項目

使用 koa-generator 腳手架工具html

npm install koa-generator -g #全局安裝
koa2 demo #建立demo項目
cd demo && npm install #安裝依賴

默認生成項目結構以下前端

clipboard.png

修改配置

用腳手架生成的項目,默認是服務器渲染,即響應的是html視圖。而咱們要開發接口,響應的是json數據。因此要刪除渲染視圖的代碼。增長響應json的配置。node

首先刪除views文件夾,接下來就是修改 app.jslinux

1. 刪除視圖配置

如下是要刪除的代碼nginx

const views = require('koa-views')
app.use(views(__dirname + '/views', {
  extension: 'pug'
}))

2. 修改路由的註冊方式,經過遍歷routes文件夾讀取文件

const fs =  require('fs')
fs.readdirSync('./routes').forEach(route=> {
    let api = require(`./routes/${route}`)
    app.use(api.routes(), api.allowedMethods())
})

3. 添加jwt認證,同時過濾不須要認證的路由,如獲取token

const jwt = require('koa-jwt')
app.use(jwt({ secret: 'yourstr' }).unless({
    path: [
        /^\/$/, /\/token/, /\/wechat/,
        { url: /\/papers/, methods: ['GET'] }
    ]
}));

4. 全局錯誤捕獲並響應

// error
app.use(async (ctx, next) => {
    try {
        await next()
    } catch(err) {
        ctx.status = err.statusCode || err.status || 500;
        ctx.body = err.message
        ctx.app.emit('error', err, ctx);
    }
})

5. 跨域處理

當接口發佈到線上,前端經過ajax請求時,會報跨域的錯誤。koa2使用koa2-cors這個庫很是方便的實現了跨域配置,使用起來也很簡單git

const cors = require('koa2-cors');
app.use(cors());

鏈接數據庫

咱們使用mongodb數據庫,在koa2中使用mongoose這個庫來管理整個數據庫的操做。github

1. 建立配置文件

根目錄下新建config文件夾,新建mongo.jsajax

// config/mongo.js
const mongoose = require('mongoose').set('debug', true);
const options = {
    autoReconnect: true
}

// username 數據庫用戶名
// password 數據庫密碼
// localhost 數據庫ip
// dbname 數據庫名稱
const url = 'mongodb://username:password@localhost:27017/dbname'

module.exports = {
    connect: ()=> {            
        mongoose.connect(url,options)
        let db = mongoose.connection
        db.on('error', console.error.bind(console, '鏈接錯誤:'));
        db.once('open', ()=> {
            console.log('mongodb connect suucess');
        })
    }
}

而後在app.js中引入mongodb

const mongoConf = require('./config/mongo');
mongoConf.connect();

鏈接數據庫完成!數據庫

2. Schema 和 Model

mongoose有兩個核心概念,SchemaModel。Schema是預先定義的數據庫模型骨架,定義集合存儲的數據結構;Model是依據Schema構造生成的模型,有數據庫操做的能力。

下面是案例,新建一個用戶集合:

根目錄下新建models文件夾,新建users.js

const mongoose = require('mongoose');
mongoose.Promise = global.Promise;

const Schema = mongoose.Schema
const ObjectId = mongoose.Types.ObjectId

// Schema
const usersSchema = new Schema({
    _id: { type: ObjectId }, // 默認生成,不加也能夠
    username: { type: String, required: [true,'username不能爲空'] },
    sex: { type: String, enum: ['man','woman'], required: [true,'sex不能爲空'] },
    age: { type: Number required: [true,'age不能爲空'] },
    avatar: { type: String, default: '' }
})

// Model
const users = mongoose.model('users',usersSchema);

module.exports = users;

這樣,一個用戶集合的model就建好了,接下來在路由中直接引入這個model,就能夠進行數據庫操做了

註冊路由

按照app.js的配置,routes文件夾下每個文件都要註冊成爲一個路由

1. 基本結構

一個基本的, RESTful風格的用戶增查改刪接口路由文件以下,包含了增查改刪的通用寫法

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

router.prefix('/users')

router.get('/', function (ctx, next) {
    ctx.body = '獲取全部用戶'
})

router.get('/:id', function (ctx, next) {
    let id = ctx.params.id
    ctx.body = '獲取單個用戶'
})

router.post('/', function (ctx, next) {
    let data = ctx.request.body
    ctx.body = '新增用戶'
})

router.put('/:id', function (ctx, next) {
    let id = ctx.params.id
    ctx.body = '修改用戶信息'
})

router.delete('/:id', function (ctx, next) {
    let id = ctx.params.id
    ctx.body = '刪除用戶'
})

module.exports = router

2. 請求參數驗證

任何一次請求接口傳來的參數,首先要在最前面作一次參數驗證。若是請求參數不合法,那麼直接返回錯誤信息,無需繼續走下面的業務邏輯。

參數驗證,推薦使用 Joi 這個庫,它是 hapijs 內置的參數驗證模塊,也是使用Schema定義數據結構。

好比建立用戶接口,對用戶傳來的數據進行驗證

const Joi = require('joi')

router.post('/', function (ctx, next) {
    let data = ctx.request.body
    let schema = Joi.object().keys({
        username: Joi.string().required(),
        sex: Joi.string().required(),
        age: Joi.number().required()
    })
    let result = Joi.validate(data, schema);
    if(result.error) {
        return ctx.body = result.error.details
    }
    let reqdata = result.value;  #通過驗證後的數據
})

這樣就完成了一個簡單的驗證,具體驗證請看joi文檔

3. 數據庫操做

以前已經建立了users的model,如今咱們能夠直接在路由文件中使用該模塊,進行數據庫操做

// 引入上一步建立的model
const Users = require('../models/users');

router.get('/', async (ctx, next)=> {
    ctx.body = await Users.find()
})

router.get('/:_id', async (ctx, next)=> {
    let _id = ctx.params._id
    ctx.body = await Users.findOne({_id})
})

// 建立用戶
router.post('/', async (ctx, next)=> {
    let data = ctx.request.body
    ctx.body = await Users.create(data)
})

router.put('/:_id', async (ctx, next)=> {
    let _id = ctx.params._id
    let data = ctx.request.body
    ctx.body = await Users.update({_id}, { $set: data }, {
        runValidators: true
    })
})

router.delete('/:_id', async (ctx, next)=> {
    let _id = ctx.params._id
    ctx.body = await Users.deleteOne({_id})
})

這是基本的增查改刪的操做。這裏用到了koa2最大的亮點,就是asyncawait異步處理方案。只要await 後面返回的是 promise,就能夠直接使用。這比在 express 框架上使用 then 方法處理要優雅的多的多。

上一步講的請求參數驗證,是第一層驗證。其實在model操做中,數據進入數據庫時,也會進行一層驗證,就是mongoose的Schema定義的數據類型和字段,若是不匹配,則會拒絕寫入並返回錯誤。這就是mongoose的好處之一,能夠防止寫入不規範的數據。

這裏不作mongoose的詳解,附上文檔地址:mongoose

運行與部署

1. pm2

應用啓動文件是 www/bin,因此咱們能夠經過 node www/bin 開啓動應用,默認是9000端口。
這樣啓動會有一個問題,就是在修改代碼以後,程序不會自動運行最新的代碼,須要手動斷開從新啓動。

pm2的誕生就是用來解決這個問題。他是一個nodejs應用程序管理器,經過pm2啓動nodejs應用,開啓監聽模式,它就能夠自動監聽文件變化重啓應用。

固然pm2的做用還有不少,首先啓動應用:

pm2 start --name koa2 bin/www --watch

結果以下:

clipboard.png

而後能夠刪除或重啓:

pm2 list  # 查看進程列表
pm2 restart koa2 # 重啓名稱爲koa2的應用
pm2 delete koa2 # 刪除名稱爲koa2的進程
pm2 logs koa2 # 查看名稱爲koa2的進程日誌

2. nginx配置

koa2應用在linux服務端部署,首先須要pm2來啓動應用。可是koa2項目啓動通常不使用80端口,因此在線上部署時,還須要nginx作反向代理以及域名配置。

配置以下:

server {
    listen 80;
    server_name api.xxxxx.com;
    location / {
        proxy_pass http://127.0.0.1:9000;
        #兼容scoket.io
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }
}

這樣訪問 api.xxxxx.com 就能訪問koa2的應用了!

若是是https,須要修改下配置:

server {
    listen 80;
    server_name api.xxxxx.com;
    rewrite ^(.*) https://$host$1 permanent;
}
server {
    listen 443 ssl;
    server_name api.ruidoc.com;

    ssl on;
    ssl_certificate 1_api.xxxxx.com_bundle.crt; #ssl證書
    ssl_certificate_key 2_api.xxxxx.com.key;

    location / {
        proxy_pass http://127.0.0.1:9000;
        #兼容scoket.io
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }
}

此時你能夠上傳你的應用了!

3. 快速上傳源碼

通常上傳源碼的時候,可能會用ftp服務之類的。若是是Mac用戶,那麼能夠配置一條快捷命令,直接上傳,方便省事

rsync -avz ./* root@1.23.45.67:/home/api

root 是服務器用戶名;
1.23.45.67 是服務器IP地址;
/home/api 是源碼在服務器的存放路徑

而後輸入服務器密碼,就能夠快速上傳了,並且只會上傳修改過的源碼,很是快速。

還能夠將命令配置到package.json文件的scripts下,如

"scripts": {
    "upload": "rsync -avz ./* root@1.23.45.67:/home/api"
}

此時你能夠這樣上傳:

npm run upload

這樣配置上傳效率很是高,一塊兒試試吧!

本文由 楊成功 原創,更多原創文章關注 楊成功的全棧之路
相關文章
相關標籤/搜索