背景:
向小程序,提供http/https接口服务,存储用户数据、日志数据。
技术选型
resitify
纯粹的http服务,不涉及视图
typescript 2.1+
类型校验,规范代码
mock.js
提供mock服务
mongodb
文档结构,存储数据
rollup
js管理
node
后端服务管理
pm2
后端node进程管理
环境搭建
安装node
默认已安装node,当前使用版本v10.16.3。
初始化工程
npm init -y
//得到如下package.json:
{
"name": "restify-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"
安装依赖
//产线环境使用
npm install --save mongodb restify mockjs pm2
//开发环境使用
## 安装 rollup.js 基础模块
npm i --save-dev rollup rollup-plugin-buble
## 安装 rollup.js 编译代码混淆插件
npm i --save-dev rollup-plugin-uglify
## 安装 rollup.js 编译 Typescript 代码的插件模块
npm i --save-dev rollup-plugin-typescript typescript tslib
安装后package.json
{
"name": "restify-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "rollup -c rollup.config.js",
"start":"node dist/app.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"mockjs": "^1.1.0",
"mongodb": "^3.3.4",
"pm2": "^4.1.2",
"restify": "^8.4.0"
},
"devDependencies": {
"rollup": "^1.27.2",
"rollup-plugin-buble": "^0.19.8",
"rollup-plugin-typescript": "^1.0.1",
"rollup-plugin-uglify": "^6.0.3",
"tslib": "^1.10.0",
"typescript": "^3.7.2"
}
}
配置rollup
touch rollup.config.js
const path = require('path');
const buble = require('rollup-plugin-buble');
const typescript = require('rollup-plugin-typescript');
const resolveFile = function(filePath) {
return path.join(__dirname, filePath)
}
module.exports = [
{
input: resolveFile('src/main.ts'),
output: {
file: resolveFile('dist/app.js'),
format: 'cjs',
name: 'restify-demo',
},
plugins: [
typescript(),
buble(),
],
},
]
安装mongodb
下载mongo
# 进入 /usr/local
cd /usr/local
# 下载
sudo curl -O https://fastdl.mongodb.org/osx/mongodb-osx-ssl-x86_64-4.0.9.tgz
# 解压
sudo tar -zxvf mongodb-osx-ssl-x86_64-4.0.9.tgz
# 重命名为 mongodb 目录
sudo mv mongodb-osx-x86_64-4.0.9/ mongodb
export PATH=/usr/local/mongodb/bin:$PATH
添加mongo.conf
# 日志
systemLog:
# 日志为文件
destination: file
# 文件位置
path: /usr/local/var/log/mongodb/mongo.log
# 是否追加
logAppend: true
#进程
processManagement:
# 守护进程方式
fork: true
storage:
dbPath: /usr/local/var/mongodb
net:
# 绑定IP,默认127.0.0.1,只能本机访问
bindIp: 127.0.0.1
# 端口
port: 27017
运行mongod
mongod --config /usr/local/etc/mongo.conf
校验mongo
> mongo
MongoDB shell version v4.0.9
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("07aaf4a0-c188-4d50-9412-96a2b0625e8a") }
MongoDB server version: 4.0.9
Server has startup warnings:
2019-11-27T17:31:59.406+0800 I CONTROL [initandlisten]
2019-11-27T17:31:59.407+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database.
2019-11-27T17:31:59.408+0800 I CONTROL [initandlisten] **
hello-world
import restify from "restify";
import { Server } from "restify/lib/server";
function respond(req, res, next) {
res.send('hello ' + req.params.name);
next();
}
const server:Server = restify.createServer();
server.get('/hello/:name', respond);
server.head('/hello/:name', respond);
server.listen(8090, function() {
console.log('%s listening at %s', server.name, server.url);
});
hello-world请求
curl -is http://localhost:8090/hello/world -H 'accept: text/plain'
## 返回
'accept: text/plain'
HTTP/1.1 200 OK
Server: restify
Content-Type: text/plain
Content-Length: 11
Date: Wed, 20 Nov 2019 05:35:12 GMT
Connection: keep-alive
hello world
业务实践
依赖引入
import restify from "restify";
import { Server } from "restify/lib/server";
import Mock from 'mockjs'
import { dbConnect } from "./utils";
const mongodb = require('mongodb');
const log4js = require('log4js');
const logger = log4js.getLogger();
const server:Server = restify.createServer();
//before route choose
server.pre(restify.plugins.pre.userAgentConnection());
//after router choose ,before handler
server.use(restify.plugins.acceptParser(server.acceptable));
server.use(restify.plugins.queryParser({ mapParams: false }));
server.use(restify.plugins.bodyParser());
restify 路由配置
//set route
server.post('/add',
async function(req, res, next) {
const desc = req.body.desc;
let result = await create(desc);
req.desc = {desc:'success',data:{
desc:result,
numbrer:Mock.mock({
"number|1-100": 100
})
}};
return next();
},
function(req, res, next) {
res.send(req.desc);
return next();
}
);
server.get(
'/all',
async function(req, res, next) {
let result = await fetchAll();
req.desc = result;
return next();
},
function(req, res, next) {
res.send(req.desc);
return next();
}
)
api版本支持
function sendV1(req, res, next) {
const mockNumber = Mock.mock({
"number|1-100": 100
});
res.send(`version number:${mockNumber} with param ${req.params.name}`);
return next();
}
function sendV2(req, res, next) {
const mockNumber = Mock.mock({
"number|1-100": 100
});
res.send({ param: req.params.name,version: mockNumber});
return next();
}
server.get('/version/:name', restify.plugins.conditionalHandler([
{ version: '1.1.3', handler: sendV1 },
{ version: ['2.0.0', '2.1.0', '2.2.0'], handler: sendV2 }
]));
mongo 操作
let db;
// Get a DB connection when this module is loaded
(function getDbConnection() {
dbConnect().then((database) => {
db = database;
}).catch((err) => {
logger.error('Error while initializing DB: ' + err.message, 'lists-dao-mongogb.getDbConnection()');
});
})();
function create(description) {
return new Promise((resolve, reject) => {
let lists = db.collection('shoppingLists');
let listId = mongodb.ObjectId();
let whenCreated = Date.now();
let item = {
_id: listId,
id: listId,
description: description,
whenCreated: whenCreated,
whenUpdated: null
};
lists.insertOne(item, (err, result) => {
if (err) {
logger.error('Error occurred: ' + err.message, 'create()');
reject(err);
} else {
resolve({ data: { createdId: result.insertedId }, statusCode: 201 });
}
});
});
}
function fetchAll() {
return new Promise((resolve, reject) => {
let lists = db.collection('shoppingLists');
lists.find({}).toArray((err, documents) => {
if (err) {
logger.error('Error occurred: ' + err.message, 'fetchAll()');
reject(err);
} else {
logger.debug('Raw data: ' + JSON.stringify(documents), 'fetchAll()');
resolve({ data: JSON.stringify(documents), statusCode: (documents.length > 0) ? 200 : 404 });
}
});
});
}
db连接
const mongodb = require('mongodb');
const log4js = require('log4js');
const logger = log4js.getLogger();
// logger.level = 'debug';
let mongodbClient;
let db;
const appSettings = {
mongodb_url:'mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb',
mongodb_db_name:'mongoDemo',
}
function dbClose() {
if (mongodbClient && mongodbClient.isConnected()) {
mongodbClient.close();
}
}
export function dbConnect() {
return new Promise((resolve, reject) => {
if (db) {
resolve(db);
} else {
mongodb.MongoClient.connect(appSettings.mongodb_url, function(err, client) {
if (err) {
logger.error('Error connecting to the MongoDB URL: ' + appSettings.mongodb_url);
reject(err);
}
mongodbClient = client;
db = mongodbClient.db(appSettings.mongodb_db_name);
// Make sure connection closes when Node exits
process.on('exit', (code) => {
dbClose();
})
resolve(db);
});
}
});
}
参考文献
本文作者:前端首席体验师(CheongHu)
联系邮箱:simple2012hcz@126.com
点击查看更多内容
1人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦