我是Nodejs的新手。我正在尝试用它写一些“干净”的代码。我正在使用MySQL作为我的数据库。
我想使用MVC作为我的设计模式。目前我想将“用户”实现为CRUD。我不喜欢我的所有代码都在app.ts
我不使用一些映射器或其他只是“正常”的SQL查询。
import express = require('express')
import bodyParser = require('body-parser')
import db = require('mysql')
import session = require('express-session')
import {Connection, MysqlError} from "mysql"
let connection: Connection = db.createConnection({
host: 'localhost',
user: 'admin',
password: 'secret',
database: 'test'
});
var app = express();
app.use('/views', express.static(__dirname + '/views'))
app.use('/public', express.static(__dirname + '/public'))
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json());
app.get('/', function (req, res) {
connection.connect(function(err) {
if (err) {
console.error('error connecting: ' + err.stack);
return;
}
console.log('connected as id ' + connection.threadId);
});
});
app.listen(8080, function () {
console.log('Listening on port 8080!');
console.log('____________________________________')
console.log('____________________________________')
console.log('____________________________________')
console.log("PLEASE VISIT ➡️ ➡️ ➡️ ➡️ http://localhost:8080/views/index.html ⬅️ ⬅️ ⬅️ ⬅️")
console.log('____________________________________')
});
通常连接应该在模型中吗?我如何使用控制器和模型?我如何在app.js
中使用它们?
非常感谢你的帮助,我真的很感激。
答案 0 :(得分:1)
Node和Express没有严格的文件和文件夹结构。相反,您可以按照自己喜欢的方式构建Web应用程序。这也让我们可以自由地遵循任何模式。
让我们以一个小示例项目为例,并将其作为您希望实现的设计的灵感。我们可以使用Mongoose / MongoDB。但是在您的场景中可以使用简单的SQL查询轻松切换。 / p>
文件夹结构类似于这样,
project/
controllers/
users.js
helpers/
dbHelper.js
middlewares/
auth.js
models/
user.js
routes/
users.js
tests/
app.js
package.json
您的app.js将启动服务器并初始化所有中间件/路由。中间件可以处理会话/身份验证。
<强> app.js 强>
import express from 'express';
import bodyparser from 'body-parser';
import logger from 'logger-module';
import users from './routes/users';
import dbHelper from './helpers/dbHelper';
const app = express();
const port = process.env.PORT || 3000;
dbHelper.init();
logger.info('App is starting...');
app.use(cors());
app.use(bodyparser.json());
app.use(bodyparser.urlencoded({
extended: true,
}));
app.use('/users', users);
app.use((err, req, res, next) => {
logger.error(err);
const message = err.message || 'Server Failure';
const response = {
error: {
message,
err.stack
}
};
return res.status(500).send(response);
});
app.use((req, res) => {
res.status(404).send("Sorry can't find that!");
});
app.listen(port, (err) => {
if (err) {
logger.error(err);
}
logger.info(`App listening on port ${port}`);
});
<强> auth.js 强>
import passportJwt from 'passport-jwt';
const JwtStrategy = passportJwt.Strategy;
const ExtractJwt = passportJwt.ExtractJwt;
import User from '../models/User';
module.exports = function(passport, jwtConfig) {
var opts = {};
opts.secretOrKey = jwtConfig.secret;
opts.issuer = jwtConfig.issuer;
opts.audience = jwtConfig.audience;
opts.jwtFromRequest = ExtractJwt.fromAuthHeader();
passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
User.findOne({
_id: jwt_payload.sub
}).lean().exec(function(err, user) {
if (err) {
return done(err, false);
}
if (user) {
done(null, user);
} else {
done(null, false, 'User found in token but not found in records');
}
});
}));
};
db helper将连接到db并保存可在控制器中使用的连接实例。
import mongoose from 'mongoose';
function init() {
const DB_PORT = process.env.BC_DB_PORT;
const DB_HOST = process.env.IP;
const DB_NAME = process.env.BC_DB_NAME;
let url = `mongodb://${DB_HOST}:${DB_PORT}/${DB_NAME}`;
mongoose.connect(url, function(err) {
if (err) {
console.log(`Database connectivity error - ${url}`);
}
});
}
function getMongoose() {
return mongoose;
}
module.exports = {
init,
getMongoose
};
模型将保存您的模式,并且可以在Controllers中使用。它还将保存模型特定的逻辑,如加密密码。在您的情况下,您只需在此处保存查询。
<强> users.js 强>
import mongoose from '../helpers/dbHelper.js';
import bcrypt from 'bcrypt';
var Schema = mongoose.getMongoose().Schema;
var User = new Schema({
_id: {
type: String,
required: true
},
password: {
type: String,
required: true
},
firstname: String,
lastname: String,
email: {
type: String,
trim: true,
unique: true,
required: true
},
mobile: {
type: String,
trim: true,
unique: true,
required: true
}
}, {
timestamps: true
});
User.pre('save', function(next) {
var user = this;
if (this.isModified('password') || isNew) {
bcrypt.genSalt(10, function(err, salt) {
if (err) {
return next(err);
}
bcrypt.hash(user.password, salt, function(err, hash) {
if (err) {
return next(err);
}
user.password = hash;
next();
});
});
} else {
return next();
}
});
User.pre('findOneAndUpdate', function(next) {
var user = this;
if (this._update.password) {
bcrypt.genSalt(10, function(err, salt) {
if (err) {
return next(err);
}
bcrypt.hash(user._update.password, salt, function(err, hash) {
if (err) {
return next(err);
}
user._update.password = hash;
next();
});
});
} else {
return next();
}
});
User.methods.comparePassword = function(password, cb) {
bcrypt.compare(password, this.password, function(err, isMatch) {
if (err) {
return cb(err);
}
cb(null, isMatch);
});
};
module.exports = mongoose.model('User', User);
这些路由将持有充当服务端点的快速中间件,并将占用控制器。如果您计划使用apidoc之类的东西,路由器也是保存api文档的适当位置。
<强>路由/ users.js 强>
import {router} from "express";
import userControllerfrom '../controllers/users';
router.get("/", function(req, res, next) {
userController.findAllUsers(req, res, next);
});
router.delete("/:userId", function(req, res, next) {
userController.deleteUser(req, res, next);
});
router.get("/:userId", function(req, res, next) {
userController.findUser(req, res, next);
});
router.put("/:userId", function(req, res, next) {
userController.updateUser(req, res, next);
});
module.exports = router;
控制器将具有对模型起作用的逻辑。它们还保留模型的验证。
<强>控制器/ user.js的强>
import HttpStatus from "http-status";
import User from '../models/User';
function deleteUser(req, res, next) {
let userId = req.params.userId;
User.remove({
_id: userId
}, function(err, {
result
}) {
//Logic to handle
});
}
function findUser(req, res, next) {
let userId = req.params.userId;
User.findOne({
_id: userId
}, {
password: 0,
__v: 0
}).lean().exec().then(function(user) {
//Logic to handle
}).catch(function(err) {
err["info"] = "Error when finding user";
next(err);
});
}
function findAllUsers(req, res, next) {
User.find(req.query, {
password: 0,
__v: 0
}).lean().exec().then(function(users) {
//Logic to handle
}).catch(function(err) {
err["info"] = "Error when finding all users";
next(err);
});
}
function updateUser(req, res, next) {
let userId = req.params.userId;
User.findOneAndUpdate({
_id: userId
}, req.user, {
new: true
}, function(err, user) {
//Logic to handle
});
}
module.exports = {
deleteUser,
findUser,
findAllUsers,
updateUser
};