之前已经介绍过如何搭建express运行环境NodeJS:搭建基于express框架运行环境;所以本文只介绍如何如何使用express+MySQL搭建一个完整的后台项目,实现动态路由。
- express生成项目
- 连接数据库
- 封装动态路由
一、express生成项目
//通过生成器生成项目
express + 项目名称 //命令行自动创建项目
cd +项目名称
npm install
npm start //按照提示执行以上代码,启动express项目
修改模板渲染引擎
npm i ejs --save //安装ejs模板
//app.js
var ejs=require('ejs')
app.set('views', path.join(__dirname, 'views'));
app.engine('html', ejs.renderFile);
app.set('view engine', 'html');
二、连接数据库
首先,需要启动MySQL数据库;
其次,在项目中配置连接数据库;
1.在项目中创建config文件夹,然后创建index.js和db_config.js两个文件;
config/db_config.js文件内容如下:
//mysql配置文件
mysql = {
host: "127.0.0.1", //这是数据库的地址
user: "root", //需要用户的名字
password: "", //用户密码 ,如果你没有密码,直接双引号就是
database: "passdatabase" //数据库名字
} //好了,这样我们就能连接数据库了
module.exports = mysql; //用module.exports暴露出这个接口,
config/index.js文件内容如下:
var mysql = require('mysql');
var dbConfig = require('./db_config.js');
const pool=mysql.createPool(dbConfig);
function responseDoReturn(err,ret) {
let result={};
if(err) {
result={
code:'100',
msg: 'err'+err
};
} else {
result={
code:'0',
msg: 'success',
data:ret
}
}
return result
};
/**
* 封装query之sql带不占位符func
*/
function query(sql, callback) {
pool.getConnection(function (err, connection) {
if(err){
callback(responseDoReturn(err,null));
}else{
connection.query(sql, function (err, rows) {
connection.release();
callback(responseDoReturn(err,rows));
});
}
});
}
/**
* 封装query之sql带占位符func
*/
function queryArgs(sql,args, callback) {
pool.getConnection(function (err, connection) {
if(err){
callback(responseDoReturn(err,null));
}else{
connection.query(sql, args,function (err, rows) {
connection.release();
callback(responseDoReturn(err,rows));
});
}
});
}
//exports
module.exports = {
query: query,
queryArgs: queryArgs,
}
2.创建sql文件夹,文件夹下按照数据库的表区分模块,我的写了个user.js;
sql/user.js文件内容如下:
var user_sql={
insertOne:'insert into user (username,password,remark) values (?,?,?)',
deleteOne:'delete from user where id = ?',
updateOne:'update user set username = ?,password = ?,remark = ? where id = ?',
selectOne:'select * from user where id = ?',
selectAll:'select * from user',
selectOneByName:'select * from user where username = ?',
}
module.exports=user_sql
3.创建model文件夹,文件夹下按照数据库的表区分模块,我的写了个user.js;
model/user.js内容如下:
var userSql = require('../sql/user.js');
var db = require('../config/index.js');
function getUser(req,res,callback){
db.queryArgs(userSql.selectOneByName, req.body.username,function (result) {
callback(result);
});
}
function addUser(req,res,callback){
db.queryArgs(userSql.insertOne, [req.body.username,req.body.password,req.body.remark],function (result) {
callback(result);
});
}
module.exports = {
getUser:getUser,
addUser:addUser
}
4.创建controller文件夹,文件夹下按照数据库的表区分模块,我的写了个user.js;
controller/user.js内容如下:
let model = require('../model/user.js');
let api = {
login(req, res, next) {
},
register(req, res, next) {
new Promise((resolve, reject) => {
model.getUser(req, res, (result) => {
if (result.code == "0") {
if (result.data.length) {
res.json({
code: '0',
msg: "用户已存在"
})
} else {
resolve(result)
}
} else {
res.json(result)
}
})
}).then((result) => {
if (!result.data.length) {
model.addUser(req, res, (result) => {
if (result.code == '1') {
res.cookie("userId", result.data.insertId, {
path: '/',
maxAge: 1000 * 60 * 60
});
}
res.json(result)
})
}
})
}
}
module.exports = api
4.routes文件夹下我的写了个user.js;
routes/user.js内容如下:
var express = require('express');
var router = express.Router();
var api=require('../controller/user.js');
/* GET users listing. */
router.post('/login', function(req, res, next) {
api.login(req, res, next)
});
router.post('/register', function(req, res, next) {
api.register(req, res, next)
});
module.exports = router;
三、封装动态路由
创建untils文件夹,创建index.js文件,内容如下;
/**
* 动态遍历目录加载路由工具
* author: bling兴哥
*/
var fs = require("fs");
var path=require('path');
// 动态路由
var loadRoute = {
path : path.join(__dirname,'../routes/'),
app : null,
// 遍历目录
listDir : function(dir){
var fileList = fs.readdirSync(dir,'utf-8');
for(var i=0;i<fileList.length;i++) {
var stat = fs.lstatSync(dir + fileList[i]);
// 是目录,需要继续
if (stat.isDirectory()) {
this.listDir(dir + fileList[i] + '/');
} else {
this.loadRoute(dir + fileList[i]);
}
}
},
// 加载路由
loadRoute : function(routeFile){
console.log(routeFile);
var pathArr=routeFile.split('\\');
var routeName=pathArr[pathArr.length-1].replace(/(.*)\.\w+$/,'$1');
var route = require(routeFile.substring(0,routeFile.lastIndexOf('.')));
this.app.use("/"+routeName,route);
},
// 初始化入口
init : function(app,path){
if(!app){
console.error("系统主参数App未设置");
return false;
}
this.app = app;
this.path = path?path:this.path;
this.listDir(this.path);
}
};
module.exports = loadRoute;
app.js文件中修改后内容如下:
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var loadRoute=require('./untils/index.js');
// var bodyParser=require('body-parser');
var ejs=require('ejs');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.engine('html', ejs.renderFile);
app.set('view engine', 'html');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(function(req,res,next){
if(req.cookies.userId){
next()
}else{
if(req.path=="/user/login"||req.path=="/user/register"){
next()
}else{
res.json({
code:'10001',
msg:"当前未登录",
result:""
})
}
}
})
loadRoute.init(app);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
注意:
1.前端使用vue框架通过axios发送请求时,后台获取的参数re.body={
{username:‘222’,password:‘sss’}:’’}时,可在前端修改如下:
修改:config.headers['Content-Type'] = 'application/x-www-form-urlencoded';
为:config.headers['Content-Type'] ="application/json";