【Node.js】koa搭建简单后台服务

背景

使用前后端完全分离的方式构建项目时,在前端需要预留AJAX请求的接口,实现页面数据的展示等操作。此时,前端开发人员等待后台人员为我们写测试接口是不太现实的。所以,我们可以自己搭建一个简单的后台服务,仅仅返回前端需要的数据。


平台

使用Node.js搭建一个后台服务,后台框架选择koa,一个轻量级的框架,相较于常见的Express更便捷。实现源码


需要的模块

// load opensource code
const Koa = require('koa');
const staticServer = require('koa-static');
const KoaRouter = require('koa-router');
const bodyParser = require('koa-bodyparser');

对于一个后台服务通常需要考虑路由(静态资源路由、非静态资源路由)、参数解析以及日志。


静态资源加载

这里使用koa-static模块,直接使用npm install安装即可,使用也很方便。

const app = new Koa();
app.use(staticServer(__dirname + ‘/static’));

这里使用了“use”接口,这个可以加载中间件,拦截HTTP请求,与Express的“use”类似。它允许自己定义一个中间件,比如,自己写一个拦截用户访问的remote ip的中间件。

/**
 * 访问日志
 * 
 */
app.use(async (ctx, next) => {
    let remoteIP = ctx.request.ip;
    let origin = ctx.request.origin;
    let url = ctx.request.url;
    logger.info(`Remote IP: ${remoteIP} --> ${origin}${url}`);
    await next();
});

参数解析

通常HTTP请求使用GET或者POST方法,GET请求的参数可以直接解析请求中字符串就可以获取。但是,POST的参数稍微麻烦一些,这里我们引入“koa-bodyparser”模块,使用它来解析POST的参数。

const bodyParser = require('koa-bodyparser');
// POST参数解析
app.use(bodyParser({
    onerror: function (err, ctx) {
        ctx.throw('body parse error', 422);
    }
}));

给获取的参数预留一个统一个获取接口,为之后使用提供便利:

/**
 * GET、POST参数解析,将参数统一放置在ctx.params中
 * 
 */
app.use(async (ctx, next) => {
    if (ctx.request.method === 'GET') {
        ctx.params = ctx.request.query;
    } else if (ctx.request.method === 'POST') {
        ctx.params = ctx.request.body;
    }
    await next();
});

路由解析

“koa-router”模块可以帮助我们完成路由的解析,它提供了GET、POST、ALL等接口:

const KoaRouter = require('koa-router');
const route = new KoaRouter();
route.get('url',function handler(){});
app.use(route.routes()).use(route.allowedMethods());

路由实现设计

当请求多时,每次都去写一次GET或POST是一件很繁琐的事情,所以,提供一个通过配置完成路由设置的架构。

路由配置

将路由的URL,以处理方法的所在文件和方法名配置好,如下:

扫描二维码关注公众号,回复: 2452205 查看本文章
{
    "port": 3000,
    "https_port": 9909,
    "get": [
        {
            "url": "/getUsers",
            "file": "./interface/userinfo.js",
            "func": "getUsers"
        }
    ],
    "post": [
        {
            "url": "/getUser",
            "file": "./interface/userinfo.js",
            "func": "getUser"
        }
    ]
}

在app.js文件中一次性加载完所有预定义的路由,以及其处理方式:

/**
 * 获取请求处理方法
 * 
 * @param {String} path 文件路径
 * @param {String} method 方法名
 */
function getRoutesHandle(path, method) {
    var res = require(path);
    var ret = res[method];
    return ret;
}

// GET请求加载
getMethod.forEach(e => {
    route.get(e.url, getRoutesHandle(e.file, e.func));
});

// POST请求加载
postMethod.forEach(e => {
    route.post(e.url, getRoutesHandle(e.file, e.func));
});

实现思路:以“接口”为入口,再由接口去调用的“业务”。优点,所有接口(路由)写在配置文件中,一目了然。同时,需要修改路由时也很方便,不需要去各个文件中去查找(在Java后台中,当需要修改一个请求时,需要先找到请求所在controller层,比较麻烦)。


日志

这里的日志使用的bunyan,需要自己稍微配置下日志的输出格式,还是比较方便的:

var bunyan = require('bunyan');
var config = require('./configReaderLib.js').loadLogConfig();

var Log = bunyan.createLogger({
    src: true,
    name: 'mine',
    streams: [
        {
            type: 'rotating-file',
            level: 'error',
            path: 'log/log_error.log',// 日志输出到文件
            period: '1d', // daily rotation
            count: 3, // keep 3 back copies
        },
        {
            type: 'rotating-file',
            level: config.level === undefined ? 'info' : config.level,
            path: 'log/log_info.log',// 日志输出到文件
            period: '1d', // daily rotation
            count: 3 // keep 3 back copies
        },
        {
            level: 'debug',
            stream: process.stdout
        }
    ]
});

数据库操作

源码里面提供了MongoDB数据库的操作接口,有兴趣可以看下。

猜你喜欢

转载自blog.csdn.net/swl979623074/article/details/81272066
今日推荐