• koa2从入门到部署全过程(转载)


    本文转载自https://segmentfault.com/a/1190000019155991

    初始化项目

    使用 koa-generator 脚手架工具

    npm install koa-generator -g #全局安装
    koa2 demo #创建demo项目
    cd demo && npm install #安装依赖

    默认生成项目结构如下

    clipboard.png

    修改配置

    用脚手架生成的项目,默认是服务器渲染,即响应的是html视图。而我们要开发接口,响应的是json数据。所以要删除渲染视图的代码。增加响应json的配置。

    首先删除views文件夹,接下来就是修改 app.js

    1. 删除视图配置

    以下是要删除的代码

    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这个库非常方便的实现了跨域配置,使用起来也很简单

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

    连接数据库

    我们使用mongodb数据库,在koa2中使用mongoose这个库来管理整个数据库的操作。

    1. 创建配置文件

    根目录下新建config文件夹,新建mongo.js

    // 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中引入

    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

    这样配置上传效率非常高,一起试试吧!

  • 相关阅读:
    《白骨精学习法》 21世纪职场必备学习技巧
    英雄不问出处
    整理ArcSDE 安装过程出现问题以及解决方法系列
    ArcEngine9.1结合VS2005开发技巧2则
    推荐一界面控件DotNetBar(含附件)
    常用易忘记Oracle命令(待续)
    ArcSDE中间件技术的生命力(蔡晓兵)
    ArcSDE 的存储机制
    (收藏)ITPUB的ORACLE之常用FAQ V1.0
    ORA01691错误
  • 原文地址:https://www.cnblogs.com/wangzisheng/p/16170716.html
Copyright © 2020-2023  润新知