执行如下命令
$ express -e test
warning: option `--ejs' has been renamed to `--view=ejs'
create : test\
create : test\public\
create : test\public\javascripts\
create : test\public\images\
create : test\public\stylesheets\
create : test\public\stylesheets\style.css
create : test\routes\
create : test\routes\index.js
create : test\routes\users.js
create : test\views\
create : test\views\error.ejs
create : test\views\index.ejs
create : test\app.js
create : test\package.json
create : test\bin\
create : test\bin\www
change directory:
$ cd test
install dependencies:
$ npm install
run the app:
$ DEBUG=test:* npm start
执行如下命令,产生.git文件
$ git init
Initialized empty Git repository in D:/four/绗笁闃舵涓婅/serverRender/test/.git/
所需要的依赖包,产生node_modules文件夹
cnpm i
过滤文件,不会被上传到仓库
编写如下内容
node_modules
.DS_Store
*/.DS_Store
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*
package-lock.json
yarn.lock
1 core 存放mysql.js文件
2 config 存放数据库配置文件
3 controller 存放控制层需要的接口文件
4 middleware 存放中间键(如校验token和生成token)
执行命令
cnpm i mysql moment lodash cors jwt-simple --save-dev
数据库 时间 节流 跨域 token
const mysql = require('mysql');
const { request } = require('../app');
const pool = mysql.createPool(require("../config").dev);
pool.on('connection', (connection) => {
//logger.info("connection!");
});
pool.on('enqueue', () => {
//logger.info('Waiting for available connection slot');
});
module.exports.Pool = pool;
module.exports.getConnection = (cb) => {
if (typeof cb == "function") {
pool.getConnection(function (err, connection) {
cb(err, connection);
});
} else {
return new Promise((resolve, reject) => {
pool.getConnection((err, connection) => {
if (err) {
reject(err);
} else {
resolve(connection);
}
});
});
}
};
module.exports.exec = (sql, values, cb) => {
if (typeof cb == "function") {
pool.getConnection((err, connection) => {
if (err) {
connection.release();
cb(err);
} else {
connection.query(sql, values, (error, rows) => {
connection.release();
cb(error, rows);
});
}
});
} else {
return new Promise((resolve, reject) => {
pool.getConnection((err, connection) => {
if (err) {
connection.release();
reject(err);
} else {
connection.query(sql, values, (error, rows) => {
connection.release();
if (error)
reject(error);
else
resolve(rows);
});
}
});
});
}
};
module.exports.beginTransaction = (connection, cb) => {
if (typeof cb == "function") {
connection.beginTransaction(function (err) {
if (err) {
throw err;
}
cb(null, connection);
});
} else {
return new Promise((resolve, reject) => {
connection.beginTransaction(function (err) {
if (err) {
reject(err);
} else {
resolve(connection);
}
});
});
}
};
module.exports.rollback = (connection, cb) => {
if (typeof cb == "function") {
connection.rollback(function () {
connection.release();
cb && cb();
});
} else {
return new Promise((resolve, reject) => {
connection.rollback(function (err) {
connection.release();
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
};
module.exports.commit = (connection, cb) => {
if (typeof cb == "function") {
connection.commit(function (err) {
if (err) {
connection.rollback(function () {
cb && cb(err);
throw err;
});
}
connection.release();
cb && cb();
});
} else {
return new Promise((resolve, reject) => {
connection.commit(function (err) {
if (err) {
connection.rollback(function () {
reject(err);
});
}
connection.release();
resolve();
});
});
}
};
//检查是否链接失败
this.getConnection((err, connection) => {
if (err) throw err;
else {
// logger.info("connected success!");
connection.release();
}
});
/**
* 带事务
* @param sql
* @param values
* @returns {Promise}
*/
module.exports.exec2 = (connection, sql, values, cb) => {
if (typeof cb == "function") {
connection.query(sql, values, (error, rows) => {
cb(error, rows);
});
} else {
return new Promise((resolve, reject) => {
connection.query(sql, values, (error, rows) => {
if (error)
reject(error);
else
resolve(rows);
});
});
}
};
module.exports = {
// 开发的时候使用,测试数据库
dev: {
host: "127.0.0.1",
user: 'root',
password: "root",
port: 3306,
database: "test",
timeout:1000*3
},
//产品上线的时候 切换 真实数据库
pro: {
},
md5Key:"laker",
tokenKey:"youker.net",
}
const jwt=require("jwt-simple");
module.exports={
validateToken(request,response,next){
let token=request.body.token||
request.query.token||
request.headers.token||
request.cookies.token;
if(token==undefined) response.json({msg:"请携带token"});
try {
let userObj=jwt.decode(token,require("../config").tokenKey);
request.currentUser=userObj;//得到当前登录用户信息
next();
}catch (error){
response.json({msg:"token失效"})
}
},
createToken(user){
return jwt.encode({
user,
exp:Date.now()+1000*60*60*24,
},require("../config").tokenKey)
}
}
1 创建路由(暴露路由)
2 配置路由(app.js)
3 控制层创建接口(暴露接口)
4 配置接口(路由中)
const express=require("express");
const router=express.Router();//1 创建路由
router.post("/login",require("../controller/account").login);//配置接口
module.exports=router;//2 暴露路由
//路由配置
app.use("/api",require("./routes/apiRouter"));
app.js文件
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
//路由配置
app.use("/api",require("./routes/apiRouter"));
// 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;
const db=require("../core/mysql");
class Account{
async login(request,response,next){
//1 参数
let params=[
request.body.name,
request.body.pwd
]
//2 sql语句
let loginSql="select * from userinfo where u_username=? and u_password=?;";
try {
let result=await db.exec(loginSql,params);
if(result&& result.length>=1){
delete (result[0].u_password);
let token=require("../middleware/token").createToken(result[0]);
result[0].token=token;
response.json({
msg:"登录成功",
code:200,
data:result[0],
})
}else {
response.json({
msg:"登录失败,密码或者用户名不正确",
code:200
})
}
}catch (error){
response.json({msg:"服务器异常",error,code:-200})
}
}
}
module.exports=new Account();//暴露接口
http://127.0.0.1:3000/api/login
-g全局安装后下次不需要再次安装
cnpm i apidoc -g
{
"name":"案例接口服务",
"version": "1.0.1",
"description": "接口服务文档",
"title": "interfaceServer",
"url": "http://127.0.0.1:3000"
}
async login(request,response,next){
/**
*
* @api {POST} /api/login 登录
* @apiVersion 1.0.1
* @apiName 用户登录
* @apiGroup account
* @apiParam {string} name 用户名
* @apiParam {string} pwd 密码
* @apiSuccessExample Success-Response:
* HTTP/1.1 200 OK
* {
"msg": "登录成功",
"code": 200,
"data": {
"u_id": 1,
"u_username": "lay",
"u_sex": "男",
"u_avatar": "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1600774298319&di=b8fc99db6020494fcf51788e360f5d3e&imgtype=0&src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201804%2F28%2F20180428231506_hmfjw.jpg",
"u_phone": "12342234567",
"u_email": "[email protected]",
"u_status": "1",
"u_create": "2020-09-22T08:47:29.000Z",
"u_nick": "崽崽2",
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjp7InVfaWQiOjEsInVfdXNlcm5hbWUiOiJsYXkiLCJ1X3NleCI6IueUtyIsInVfYXZhdGFyIjoiaHR0cHM6Ly90aW1nc2EuYmFpZHUuY29tL3RpbWc_aW1hZ2UmcXVhbGl0eT04MCZzaXplPWI5OTk5XzEwMDAwJnNlYz0xNjAwNzc0Mjk4MzE5JmRpPWI4ZmM5OWRiNjAyMDQ5NGZjZjUxNzg4ZTM2MGY1ZDNlJmltZ3R5cGU9MCZzcmM9aHR0cCUzQSUyRiUyRmItc3NsLmR1aXRhbmcuY29tJTJGdXBsb2FkcyUyRml0ZW0lMkYyMDE4MDQlMkYyOCUyRjIwMTgwNDI4MjMxNTA2X2htZmp3LmpwZyIsInVfcGhvbmUiOiIxMjM0MjIzNDU2NyIsInVfZW1haWwiOiIxMjNAcXEuY29tIiwidV9zdGF0dXMiOiIxIiwidV9jcmVhdGUiOiIyMDIwLTA5LTIyVDA4OjQ3OjI5LjAwMFoiLCJ1X25pY2siOiLltL3ltL0yIn0sImV4cCI6MTYwMTA0MDQxMjkyOX0.NHui7Eqc0vIIV5zCSjg0mCHgg6Fa8soUptVTvaqRPyE"
}
}
*/
//1 参数
let params=[
request.body.name,
request.body.pwd
]
//2 sql语句
let loginSql="select * from userinfo where u_username=? and u_password=?;";
try {
let result=await db.exec(loginSql,params);
if(result&& result.length>=1){
delete (result[0].u_password);
let token=require("../middleware/token").createToken(result[0]);
result[0].token=token;
response.json({
msg:"登录成功",
code:200,
data:result[0],
})
}else {
response.json({
msg:"登录失败,密码或者用户名不正确",
code:200
})
}
}catch (error){
response.json({msg:"服务器异常",error,code:-200})
}
}
apidoc -i controller/ -o public/apidoc
127.0.0.1:3000/apidoc