1.Mongoose连接池
-
npm install mongoose
- 在config目录下创建mongoDB文件,将数据库相关的信息放至这个文件夹内
- 在mongoDB下创建mongo.js
//mongo.js
const mongoose = require('mongoose');
const mongodbConfig = require('./config').mongodb //获取mongo配置
console.log(mongodbConfig)
/**
* 使用 Node 自带 Promise 代替 mongoose 的 Promise,否则会报错
*/
mongoose.Promise = global.Promise;
/**
* 配置 MongoDb options
*/
function getMongodbConfig() {
let options = {
useNewUrlParser: true,
poolSize: 5, // 连接池中维护的连接数
reconnectTries: Number.MAX_VALUE,
keepAlive: 120,
}
return options;
}
/**
* 拼接 MongoDb Uri
*
*/
function getMongoUrl() {
let mongoUrl = 'mongodb://';
let dbName = mongodbConfig.db;
mongoUrl += `${mongodbConfig.host}:${mongodbConfig.port}`;
mongoUrl += `/${dbName}`;
return mongoUrl;
}
/**
* 创建 Mongo 连接,内部维护了一个连接池,全局共享
*/
console.log(new Date().getTime())
let mongoClient = mongoose.createConnection(getMongoUrl(), getMongodbConfig());
/**
* Mongo 连接成功回调
*/
mongoClient.on('connected', function() {
console.log(new Date().getTime())
console.log('Mongoose连接至 :' + getMongoUrl());
});
/**
* Mongo 连接失败回调
*/
mongoClient.on('error', function(err) {
console.log('Mongoose 连接失败,原因: ' + err);
});
/**
* Mongo 关闭连接回调
*/
mongoClient.on('disconnected', function() {
console.log('Mongoose 连接关闭');
});
/**
* 关闭 Mongo 连接
*/
function close() {
mongoClient.close();
}
module.exports = {
mongoClient: mongoClient,
close: close,
};
- 在mongoDB下创建config.js,里面存放我们数据库的名称、地址
//config.js
module.exports = {
"mongodb": {
"user": "",
"pass": "",
"host": "localhost",
"port": "27017",
"db": "blog"
}
}
2.Model
- 在config下创建models,存放我们的数据模型,一个model对应一个dao
Model介绍:
比如我们人类有一双手,一双眼睛,一个脑袋,没有尾巴,这就是模型,Model定义了这个模块的数据模型。
在代码中体现为数据管理者,Model负责对数据进行获取及存放。
数据不可能凭空生成的,要么是从服务器上面获取到的数据,要么是本地数据库中的数据,
也有可能是用户在UI上填写的表单即将上传到服务器上面存放,所以需要有数据来源。
既然Model是数据管理者,则自然由它来负责获取数据。
Controller不需要关心Model是如何拿到数据的,只管调用就行了。
数据存放的地方是在Model,而使用数据的地方是在Controller,
所以Model应该提供接口供controller访问其存放的数据(通常通过.h里面的只读属性)
- 在models下创建user.js,这是用户表的实体类,我们用mongoose的Schema创建
let { Schema } = require('mongoose');
let { mongoClient } = require('../mongoDB/mongo');
/**
* 操作 MongoDb 时需要创建两个文件 model.js 和 modelDao.js
*
* 一. 对于 Model.js 以下几部分:
* 1. Schema 必要
* 2. plugin 可选
* 3. hook 可选
* 4. 调用 mongoClient.model() 创建 Model,此处注意,Model 名称与 js 文件名一样,但首字母大写
*
* 二. 对于 modelDao.js
* 我们需要声明一个 ModelDao 的 class 继承自 BaseDao, BaseDao 中包含基本的 crud 操作,也可以根据需求自行定义
*
* 三. 外部使用
* var dao = new ModelDao()
* dao.crud();
*/
const userSchema = new Schema({
name: String,
psw: String, // lowercase 都属于 setters
}, {
runSettersOnQuery: true // 查询时是否执行 setters
});
/**
* 参数一要求与 Model 名称一致
* 参数二为 Schema
* 参数三为映射到 MongoDB 的 Collection 名
*/
console.log('实体类',new Date().getTime())
let User = mongoClient.model(`User`, userSchema, 'user');
module.exports = User;
3.DAO
- DAO的概念:
数据访问对象(data access object,DAO)是为某种类型的数据库或其他持久性机制提供一个抽象接口的对象。
通过映射应用程序对持久层的调用,DAO提供一些特定的数据操作,而无需暴露数据库细节。
- 在config文件下创建dao文件夹,dao文件夹存放一个模型对应的数据库操作
由于所有的数据库操作都是在【增删查改】的基础上进行操作,所以我们写了给basedao一个公共js
让其他的dao继承这个basedao
- 在dao文件下创建basedao.js
//basedao.js
class BaseDao {
/**
* 子类构造传入对应的 Model 类
*
* @param Model
*/
constructor(Model) {
this.Model = Model;
}
/**
* 使用 Model 的 静态方法 create() 添加 doc
*
* @param obj 构造实体的对象
* @returns {Promise}
*/
create(obj) {
return new Promise((resolve, reject) => {
let entity = new this.Model(obj);
this.Model.create(entity, (error, result) => {
if (error) {
console.log('create error--> ', error);
reject(error);
} else {
console.log('create result--> ', result);
resolve(result)
}
});
});
}
/**
* 使用 Model save() 添加 doc
*
* @param obj 构造实体的对象
* @returns {Promise}
*/
save(obj) {
return new Promise((resolve, reject) => {
let entity = new this.Model(obj);
entity.save((error, result) => {
if (error) {
console.log('save error--> ', error);
reject(error);
} else {
console.log('save result--> ', result);
resolve(result)
}
});
});
}
/**
* 查询所有符合条件 docs
*
* @param condition 查找条件
* @param constraints
* @returns {Promise}
*/
findAll(condition, constraints) {
return new Promise((resolve, reject) => {
this.Model.find(condition, constraints ? constraints : null, (error, results) => {
if (error) {
console.log('findAll error--> ', error);
reject(error);
} else {
console.log('findAll results--> ', results);
resolve(results);
}
});
});
}
/**
* 查找符合条件的第一条 doc
*
* @param condition
* @param constraints
* @returns {Promise}
*/
findOne(condition, constraints) {
return new Promise((resolve, reject) => {
this.Model.findOne(condition, constraints ? constraints : null, (error, results) => {
if (error) {
console.log('findOne error--> ', error);
reject(error);
} else {
console.log('findOne results--> ', results);
resolve(results);
}
});
});
}
/**
* 查找排序之后的第一条
*
* @param condition
* @param orderColumn
* @param orderType
* @returns {Promise}
*/
findOneByOrder(condition, orderColumn, orderType) {
return new Promise((resolve, reject) => {
this.Model.findOne(condition)
.sort({
[orderColumn]: orderType })
.exec(function(err, record) {
console.log(record);
if (err) {
reject(err);
} else {
resolve(record);
}
});
});
}
/**
* 更新 docs
*
* @param condition 查找条件
* @param updater 更新操作
* @returns {Promise}
*/
update(condition, updater) {
return new Promise((resolve, reject) => {
this.Model.update(condition, updater, (error, results) => {
if (error) {
console.log('update error--> ', error);
reject(error);
} else {
console.log('update results--> ', results);
resolve(results);
}
});
});
}
/**
* 移除 doc
*
* @param condition 查找条件
* @returns {Promise}
*/
remove(condition) {
return new Promise((resolve, reject) => {
this.Model.remove(condition, (error, result) => {
if (error) {
console.log('remove error--> ', error);
reject(error);
} else {
console.log('remove result--> ', result);
resolve(result);
}
});
});
}
}
module.exports = BaseDao;
- 在dao文件下创建userdao.js用来继承basedao.js
//userdao.js
const BaseDao = require('./basedao')
const User = require('../models/user')
class UserDao extends BaseDao {
constructor() {
super(User)
}
}
module.exports = UserDao;
4.以上就是mongoose连接池、MVC模式设计
有了连接池、数据操作,接下来就是调用
- 在routes 下创建 userAPI.js
//userAPI.js
var express = require('express');
const User = require('../config/models/user')
const UserDao = require('../config/dao/userdao');
const JwtUtil = require('../config/jwt/jwt.js'); //token工具
const AesUtil = require('../config/aes/aes.js'); //aes加密
var router = express.Router();
var userdao = new UserDao()
router.post('/login', (req, res) => {
let name = req.body.name // 前端请求头用json发送的话用 req.query 或者 req.params
//接收不到就下载一个body-parse插件来解析
let psw = req.body.psw
userdao.findOne({ name: name }).then((results) => {
console.log('findOne dao --> ', results)
if (results) {
//解密
let password = AesUtil.decryption(results.psw)
console.log('密码为:' + password)
if (psw == password) {
//登录成功,添加token
let _id = results._id.toString()
let jwt = new JwtUtil(_id)
let token = jwt.generateToken()
res.send(token)//登录成功,返回token
} else {
res.send('密码错误')
}
} else {
res.send('账号不存在')
}
});
})
5.API写好了,在app.js中引入userAPI.js
//app.js
const express = require("express");
const bodyParser = require("body-parser")
const app = express();
// 跨域设置
app.all("*", function(req, res, next) {
res.header("Access-Control-Allow-Credentials", true);
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With,Content-Type");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header("Access-Control-Expose-Headers", "*");
res.header("Content-Type", "application/json; charset=utf-8");
next();
});
// 获取内容
app.use(bodyParser.json())// 解析 application/json
app.use(bodyParser.urlencoded({ extended: true }))// 解析 application/x-www-form-urlencoded
app.use("/user", require("./routes/userAPI.js"));
app.get('/', (req, res) => {
res.send('api');
});
const port = process.env.PORT || 3001;
app.listen(port, () => {
console.log('Express server listening on port ' + port);
});
module.exports = app;
使用http://localhost:3001/user/login就可以访问了