nodejs开发服务端
mongodb
全局安装express-generator
npm i express-generator -g
搭建express后端项目
express express_project
项目结构
- app.js——项目入口(主要配置接口的一级路径和引入表现层)
- routes——表现层(将服务层返回的处理结果响应给前端)
- service——服务层(对持久层返回的数据操作结果进行逻辑处理)
- dao——持久层
- models——存放mongoose构建的数据模型
- database.js——连接数据库
- studentDao.js——数据库操作代码(增删改查)
安装nodemon插件
npm i nodemon -g
更改app.js文件项目启动方式
// module.exports = app;
// 更改启动命令,全局安装nodemon,服务器代码发生更改自动重启项目
app.listen(3000, () => {
console.log('3000端口启动成功');
});
在dao/database.js连接mongodb
/* 连接数据库代码 */
// 引入mongoose
const mongoose = require('mongoose');
// 定义数据库地址
const dbURL = 'mongodb://127.0.0.1:27017/users';
// 开始连接数据库
mongoose.set('strictQuery', false);
mongoose.connect(dbURL);
mongoose.connection.on('connected', () => {
console.log(dbURL, '数据库连接成功');
});
数据模型构建示例
// 数据集合配置
const { model, Schema } = require('mongoose');
// 定义集合结构,数据类型,Schema是构造函数 需要new
const studentSchema = new Schema(
{
// 定义集合中数据类型
username: String,
password: String,
// 需要定义id类型时,Schema.Types.ObjectId
},
{ versionKey: false }
);
// 用定义好的集合结构来构造数据模型 参数(模型名字,模型结构,集合名字)
const studentModel = model('studentModel', studentSchema, 'students');
module.exports.studentModel = studentModel;
持久层示例
const { teacherModel } = require('./model/teacherModel');
// 查询所有教师
module.exports.getTeachers = async () => {
return await teacherModel.find();
};
// 添加
module.exports.addTeacher = async data => {
return await teacherModel.create(data);
};
// 删除
module.exports.delTeacher = async id => {
// 删除满足条件的一条数据 deleteOne
return await teacherModel.deleteOne(id);
};
服务层示例
const { getTeachers, addTeacher, delTeacher } = require('../dao/teacherDao');
// 获取
module.exports.getTeachers = async () => {
try {
const list = await getTeachers();
return {
msg: 'success',
status: 1,
list,
};
} catch (error) {
console.log('error--->', error);
return {
msg: 'error',
status: 0,
};
}
};
表现层示例
var express = require('express');
var router = express.Router();
// 服务层方法
const { getTeachers, addTeacher,delTeacher } = require('../service/teacherService');
// 获取教师列表
router.get('/getTeachers', async function (req, res, next) {
const res1 = await getTeachers();
res.send(res1);
});
// 添加
router.post('/addTeacher', async function (req, res, next) {
const form=req.body
const res1 = await addTeacher(form);
res.send(res1);
});
// 删除
router.post('/delTeacher', async function (req, res, next) {
const id=req.body
const res1 = await delTeacher(id);
res.send(res1);
});
module.exports = router;
一些API(ps:这些方法都是异步的)
1.添加数据 teacherModel.create(object)
2.删除数据 teacherModel.deleteOone(object)
3.修改数据 teacherModel.updateOne(object)
4.查询数据 teacherModel.find(object) 没有参数全部返回
4.1 多表联查 teacherModel.find().populate('studentId') 教师联查学生表
4.2 多表联查 teacherModel.find().populate('studentId').populate('staffId') 教师联查学生,教师联查员工
4.3 多表联查 teacherModel.find().populate({
path:'studentId',
populate:{
path:'staffId'
}
}) 教师联查学生,学生联查员工
4.4 限制请求条数 teacherModel.find(object).limit(number)
4.4 跳过请求条数 teacherModel.find(object).skip(number)
4.5 统计数据条数 teacherModel.countDocuments()
密码加密方式
-
md5
-
bcrypt
-
npm i bcrypt -
const newPwd = bcrypt.hashSync(pwd) 参数传入用户输入的密码 -
登录时,将用户输入的密码,与根据用户名在数据库查找出来的账户密码进行对比,返回布尔值true或false,判断用户是否输入正确
const isLogin = bcrypt.compareSync(password, res[0].password);
-
身份认证token
安装json web token插件
npm i jsonwebtoken
jwt用法
const jwt = require('jsonwebtoken')
// 生成token的参数:存储的用户信息,密钥字符串(随便写),过期时间
const token = jwt.sign({ username }, 'isSign', { expiresIn: 60 });
安装express-jwt插件(用于验证token)
npm i express-jwt
暴露jwt验证
// 后端开始验证 utils/jwt.js 如果方法报错,自行去npm官网检查语法是否有更新
const { expressjwt: jwt } = require('express-jwt');
const jwtAuth = jwt({
secret: 'isSign', // 验证的密钥字符串
algorithms: ['HS256'], // 设置jwt的算法为HS256 新版插件配置参数
credentialRequired: false, // 不带token的请求头是否验证 false——不需验证,直接报错即可
}).unless({
path: ['/users/login', '/users/isAccess', '/users/register'], // 设置不需要携带token的路径
});
module.exports = jwtAuth;
在app.js文件,配置一级路径前去验证token
const jwtAuth = require('./utils/jwt.js')
app.use(jwtAuth)
jwt解码token,获取用户信息
- 因为生成token的时候,存放了用户的部分信息,所以通过对token解码,可以获取到这部分内容
- 生成token时也可以放入用户ID,解码时获取ID,通过ID获取到用户在数据库中的信息
// 解码,认证身份
router.get('/isLogin', async function (req, res, next) {
let authStr = req.get('Authorization');
authStr = authStr.split(' ')[1];
const { username } = jwt.verify(authStr, 'isSign');
res.send({
msg: 'success',
status: 1,
username,
});
});
RESTful接口规范
-
这是一种对于后端的接口规范,主要体现在接口路径以及请求类型上
1.接口统一使用单一的一级路径,例如 '/user' 2.请求类型 get 查询,获取 post 提交 put 修改 delete 删除 3.如果接口需要传id,统一在接口路径拼接 前端发送 '/user' + id 后端接收 '/user:id' 回调参数中使用 req.query接收 最好不要混淆规范方式,这种id接收方式不会辨别还有没有二级路由
跨域处理
jsonp
axios不适用- 只能解决
get请求
$.ajax({
url: "http://10.128.119.119/api/get/username",
type: "GET",
dataType: "jsonp",
});
CORS
// app.js var app = express(); 的下面位置添加代码
var app = express();
var allowCrossDomain = function (req, res, next) {
// 设置允许跨域访问的请求源(* 表示接受任意域名的请求)
res.header("Access-Control-Allow-Origin","*");
// 设置允许跨域访问的请求头,如果请求包含token,还要加上Authorization
res.header("Access-Control-Allow-Headers","X-Requested-With,Origin,Content-Type,Accept,Authorization");
// 设置允许跨域访问的请求类型
res.header("Access-Control-Allow-Methods","PUT,POST,DELETE,GET,OPTIONS,PATCH");
// 同意cookie 发送到服务器(如果要发送cookie,Access-Control-Allow-Origin 不能设置为*)
res.header("Access-Control-Allow-Credentials","true");
next();
}
app.use(allowCrossDomain)
代理服务器中间层nodejs
-
传统的开发中存在着前后端之前还有一层nodejs中间层交给前端处理请求响应逻辑
-
在这个中间层可以做一些数据的额外处理
-
步骤
-
创建一个中间层
nodejs项目 -
在中间层项目中安装
http-proxy-middlewarenpm i http-proxy-middleware -
在
app.js文件,一级路径配置之前配置代理const { createProxyMiddelware } = require('http-proxy-middleware') const options = { target: 'http://localhost:3000', // 目标服务器的host changeOrigin: true // 是否需要改变原始主机头为目标 pathRewrite:{ // 重写请求 '^/api': '/', // 所有以'/api'开头的请求,'/api'都会重写为 '/' } } // 写在 var app = express(); 之后 app.use('/api', createProxyMiddleware(options)); // proxy(options)即创建代理 -
大部分情况下可以通过上述方式代理转发,但是登录注册这类请求,需要现在中间层作额外加密处理,再进行转发,这个时候
http-proxy-middleware中间件就不可用了 -
需要用到另外的模块
request-promisenpm i request request-promise -
这些数据处理需要数据进到路由开始处理
-
在中间层进行数据处理后,利用
request-promise发给后端const rp = require('request-promise') router.get('/isLogin', async function (req, res, next) { const data=rp({ method: 'post', url: 'http://localhost:3001/user/login', // 后端服务器请求路径 body: { username, password, }, json:true // 需要后端返回json格式 }); // 数据返回给前端 res.send(data) });
-