这是一篇学习笔记,主要记录使用node.js完成一个小型服务器的搭建。 web服务框架选用koa,数据库选用MongoDB,数据库操作库选用mongoose,原因是这个以前看过一点有一点印象。
服务器搭建
安装
在自己喜欢的位置创建一个文件夹,然后一路回车
koa-study npm init
下一步安装koa 官网 Koa (koajs) -- 基于 Node.js 平台的下一代 web 开发框架 | Koajs 中文文档 (bootcss.com)
npm i koa
项目根目录下创建src文件夹创建项目入口文件server.js 先跑一下官网的hello word
// server.js
const Koa = require('koa');
const app = new Koa();
app.use(async ctx => {
ctx.body = 'Hello World';
});
app.listen(3000);
# 进入src文件夹
cd src/
# 启动node
node server.js
然后访问一下
路由
开始之前先确定一下做管理台需要什么。
- 登录注册
- 管理信息
- 保存文件
下面做自己的服务器,创建一个app.js。server.js只用来入口文件,app.js作为项目的主文件。
// app.js
const Koa = require('koa')
const app = new Koa();
module.exports = app;
// server.js
const app = require('./app');
const server = app.listen(3030, () => {
console.log('Server is running at http://localhost:3000');
});
module.exports = server
引入koa-router 懂得都懂不废话了
npm i koa-router
在src下创建route用来管理路由
// src/route/index.js
const Router = require('koa-router');
const router = new Router();
然后我希望这个可以自动扫描所有的路由文件,自动导入。网上借鉴了一下
// 目录结构
src
-route
--index.js
--routes
---login.js
---file.js
---info.js
// src/route/index.js
const fs = require('fs');
const Router = require('koa-router');
const router = new Router();
function initRouter(app) {
// 先导入fs模块,然后用readdirSync列出文件 这里可以用sync是因为启动时只运行一次,不存在性能问题:
const files = fs.readdirSync(__dirname + '/routes');
// 过滤出.js文件:
const js_files = files.filter((f) => {
return f.endsWith('.js');
});
// 处理每个js文件:
for (const f of js_files) {
// 导入js文件:
const mapping = require(__dirname + '/routes/' + f);
for (const url in mapping) {
if (url.startsWith('GET')) {
// 如果url类似"GET xxx":
const path = url.substring(4);
router.get(path, mapping[url]);
} else if (url.startsWith('POST ')) {
// 如果url类似"POST xxx":
const path = url.substring(5);
router.post(path, mapping[url]);
console.log(`register POST ${path}-${typeof mapping[url]}`);
} else {
// 无效的URL:
console.log(`invalid URL: ${url}`);
}
}
}
app.use(router.routes());
}
module.exports = initRouter;
// src/route/routes/login.js
const login = async (ctx) => {
ctx.response.body = { messag: '这是登录接口' }
}
module.exports = {
'GET /api/account/login': login,
};
index.js暴露出一个initRouter方法,在app中引入使用
// src/app.js
const Koa = require('koa')
const app = new Koa();
const initRouter = require('./route/index')
initRouter(app);
module.exports = app;
postman跑一下是好使的
MongoDB数据库
下载解压MongoDB
链接
sudo mv mongodb-macos-x86_64-4.2.15/ mongodb
配置环境变量,这里是zsh
先打开bash配置文件
~/.bash_profile
vi ~/.bash_profile
将需要添加的变量在~/.bash_profile中导出
export PATH=${PATH}:/usr/local/mongoDB/bin
这样生效后,bash shell中就有这两个环境变量了 然后打开zsh的配置文件~/.zshrc
vi ~/.zshrc
如果根目录没有.zshrc的话,执行下面的命令
touch ~/.zshrc vi ~/.zshrc
在~/.zshrc最下边添加如下内容:
export PATH=${PATH}:/usr/local/mongoDB/bin
最后退出终端,重新启动,再次进入zsh的时候,会生效配置文件。通过
mongo -version
查看添加的环境变量是否生效。
注意:如果不需要在bash shell中使用环境变量,1,2步骤可以不做,直接在.zshrc中进行修改即可。
创建日志及数据存放的目录
数据存放目录
sudo mkdir -p /usr/local/var/mongodb
日志存放目录
sudo mkdir -p /usr/local/var/log/mongodb
接下来要确保当前用户对以上两个目录有读写的权限
以上 ajiao 是我电脑上的用户,你这边需要根据你当前对用户名来修改
sudo chown ajiao /usr/local/var/mongodb
sudo chown ajiao /usr/local/var/log/mongodb
接下来我们使用以下命令在后台启动 mongodb:
mongod --dbpath /usr/local/var/mongodb --logpath /usr/local/var/log/mongodb/mongo.log --fork
- --dbpath 设置数据存放目录
- --logpath 设置日志存放目录
- --fork 在后台运行
如果不想在后端运行,而是在控制台上查看运行过程可以直接设置配置文件启动:
mongod --config /usr/local/etc/mongod.conf
查看 mongod 服务是否启动:
ps aux | grep -v grep | grep mongod
使用以上命令如果看到有 mongod 的记录表示运行成功。
启动后我们可以使用 mongo 命令打开一个终端:
☁ ~ mongo
MongoDB shell version v5.0.5
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("95fe5c6e-f0fc-460c-88d7-89c3f3d37ddd") }
MongoDB server version: 5.0.5
本节参考菜鸟教程Mac OSX 平台安装 MongoDB | 菜鸟教程 (runoob.com)
mongoose
- 安装
npm i mongoose --save
在项目中简单的封装一下
在src下新建db文件夹
// src/db/initDB
const mongoose = require('mongoose');
const DB_URL = 'mongodb://localhost:27017/runoob';
mongoose.connect(DB_URL);
mongoose.connection.on('connected', function () {
console.log('Mongoose connection open to ' + DB_URL);
});
mongoose.connection.on('error', function (err) {
console.log('Mongoose connection error: ' + err);
});
mongoose.connection.on('disconnected', function () {
console.log('Mongoose connection disconnected');
});
module.exports = mongoose;
// src/db/index
const m = require('./initDb.js');
const Schema = m.Schema;
class Mongodb {
constructor(schemaOpt, tableName) {
let schema = new Schema(schemaOpt)
this.model = m.model(tableName, schema)
}
// 查询
query(params) {
return new Promise((resolve, reject) => {
this.model.find(params, (err, res) => {
if (err) {
reject(err);
}
resolve(res);
});
});
}
queryOne(params) {
return new Promise((resolve, reject) => {
this.model.findOne(params, (err, res) => {
if (err) {
reject(err);
}
resolve(res);
});
});
}
// 保存
save(obj) {
const m = new this.model(obj);
return new Promise((resolve, reject) => {
m.save((err, res) => {
if (err) {
reject(err);
}
resolve(res);
console.log(res);
});
});
}
}
module.exports = Mongodb;
接下来就可以使用了
// src/route/routes/login.js
const userSchma = {
userName: String,
passWord: String,
uuid: String,
}
const DB = require('../../db/index')
const db = new DB(userSchma, 'userTable')
const registe = async (ctx) => {
const { body } = ctx.request
// 检查用户名是否存在
const userName = await db.queryOne({ 'userName': body.userName });
if (userName) {
ctx.response.body = { message: '用户名已存在', success: false, code: 400 }
} else {
try {
db.save({
userName: body.userName,
password: body.password,
uuid: tool.createId(),
createTime: new Date(),
})
ctx.response.body = { message: '创建成功', code: 200 }
} catch (error) {
ctx.response.status = 500
ctx.response.body = { message: '服务器开小差了', code: 400 }
}
}
}