中间件(需要使用express)
本质上是一个函数,包含三个参数
request
、 response
、next
作用
- 执行任何代码
- 修改请求和响应对象
- 终结请求-响应循环(让一次请求得到响应)
- 调用堆栈中的下一个中间件或者路由
分类
-
应用级中间件(全局)(过滤非法的请求,例如防盗链)
-
第三方中间件(通过npm下载的中间件)
-
内置中间件(框架内部内置的中间件)
-
路由中间件(Router)
应用中间件
第一种使用全局中间件
所有的请求都会进入该中间件
const express = require('express');
const app = express();
// 应用级中间件
app.use((req, res, next) => {
res.send('这是中间件的响应');
});
// 根路由
app.get('/', (req, res) => {
res.send('这是根路由响应');
});
app.get('/1', (req, res) => {
res.send('这是一级路由');
});
app.get('/1/2', (req, res) => {
res.send('这是二级路由');
});
app.listen(8080, (err) => {
if (!err) {
console.log('ok');
} else {
console.log(err);
}
});
- 访问根路由
- 访问一级路由
- 访问二级路由
访问的时候我们发现,无论是请求的哪个路由,都是返回应用级中间件的响应,且后序路由不在执行,当我们调用next后,便可以访问到目标路由。
将应用级中间件写在请求的任意位置,请求会依照代码顺序执行,若是执行到该中间件,那么它科能会影响到下一级中间件(若在一级与二级路由之间设置一个应用级中间件且无next,那么智能响应一级路由之前的路由,二级路由是无法访问到的)
在express中,定义路由和中间件的时候,根据定义顺序,将每一个中间件或者路由放在一个类似于数组的容器中,当请求过来的时候,依次从容器中取出中间件和路由进行匹配,如果匹配你成功,则交由该中间件或者路由处理,如果如果全局中间件定义在最开始的位置,那么所有的请求都会进入该中间件。
对于浏览器来说,每一次请求只会有一个请求对象,和一个响应对象,后续路由使用的req和res都是同一个req,res对象
注意: 在中间件中无法在next调用之前使用返回响应
函数式中间件的定义方式
const express = require('express');
const app = express();
// 函数式应用级中间件
function middleware(request, response, next){
// 应用级中间件
app.use((req, res, next) => {
res.send('这是中间件的响应');
});
}
// 根路由
app.get('/', (req, res) => {
res.send('这是根路由响应');
});
// 使用应用中间件
app.get('/1', middleware, (req, res) => {
res.send('这是一级路由');
});
app.get('/1/2', (req, res) => {
res.send('这是二级路由');
});
app.listen(8080, (err) => {
if (!err) {
console.log('ok');
} else {
console.log(err);
}
});
区别:更加灵活,可以在需要的地方使用(依据请求的路径选择使用中间件),第一种方式更适合所有请求需要做某种操作时使用。
使用方式:传入到路由的第二个参数的位置。
第三方中间件
通过npm和yarn下载的中间件
内置中间件
express内置有一些中间件
静态文件
可以通过express.staict设置静态文件
app.use(express.staict(__dirname + '/public'));
// 将当前文件夹下的public文件夹设置为静态访问
注意:访问静态文件夹内的文件需要添加上后缀
路由器
express框架中引入了路由器的概念,使用了路由器可以使代码结构功能更加清晰,便于维护
server文件
/*
* 基础页面
* */
const express = require('express');
const app = express();
// 解析post传递的参数
app.use(express.urlencoded({extended: false}));
// 解析json
app.use(express.json());
// 加载路由器
const {router} = require('./Router/router');
// 使用路由器中间件
app.use(router());
app.listen(3300, (err) => {
if (err) {
console.log(err);
} else {
console.log('ok');
}
});
router
/*
* 路由器模块
* */
// 加载路由方法
const {Router} = require('express');
// 创建路由器实例
const router = Router();
// 加载 fs文件模块 解析绝对路径方法
const {moudule:{fs, resolve}} = require('../module/module');
router.get('/', (req, res) => {
let path = resolve(__dirname, '../public/index.html');
let html = '';
let rs = fs.createReadStream(path, {
highWaterMark: 10 * 1024 * 1024
});
rs.on('open', () => {
console.log('可读开启');
});
rs.on('close', () => {
console.log('可读关闭');
res.send(html);
});
rs.on('data', (data) => {
html += data;
});
});
router.post('/login', (req, res) => {
let {body: {uname, pwd}} = req;
if (pwd === '0059') {
res.send('你好' + uname);
// res.redirect(302, '/');
} else {
res.send('password is error');
}
});
// 暴露路由器对象
module.exports.router = function () {
return router;
}
module
/*
* module 核心模块
* */
// 文件系统
const fs = require('fs');
// path模块
const {resolve} = require('path');
// 暴露
module.exports.moudule = {
fs,
resolve
};
public
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
input {
width: 200px;
height: 30px;
outline: 0;
font-size: 18px;
border: 1px solid #ccc;
border-radius: 4px;
}
input:hover {
box-shadow: 0 0 1px 1px aqua;
}
button {
padding: 10px 20px;
outline: 0;
color: #666;
font-weight: 700;
font-size: 18px;
cursor: pointer;
border-radius: 10px;
}
div {
margin-top: 30px;
}
</style>
</head>
<body>
<h1>服务器接收Get和post请求测试</h1>
<!--提交信息-->
<input type="text" name="uname" placeholder="请输入姓名"><br><br>
<input type="password" name="pwd" id="" placeholder="请输入密码"><br><br>
<button>提交</button>
<div></div>
<script>
// 获取元素
let btn = document.querySelector('button'),
input = document.querySelectorAll('input'),
div = document.querySelector('div'),
bool = true;
btn.addEventListener('click', () => {
if (bool) {
bool = false;
let obj = {uname: input[0].value, pwd: input[1].value};
let xml = new XMLHttpRequest();
xml.timeout = 1200;
xml.open('POST', 'http://localHost:3300/login', true);
// 设置解析json格式的请求头
xml.setRequestHeader("Content-type", "application/json; charset=utf-8");
xml.addEventListener('readystatechange', () => {
// 4 表示接收到全部响应数据
// 3 表示接收到部分响应数据(响应中)
// 2 表示已初始化(open调用)但是没有发送请求
// 1 表示已初始化(open调用)但是没有调用send()
// 0 表示未初始化(open未调用)
try {
if (xml.readyState === 4) {
// 表示接收到全部响应数据了
if (xml.status >= 200 && xml.status < 300) {
div.innerHTML = xml.responseText;
bool = true;
}
}
} catch (error) {
alert('出现未知错误!' + error);
}
});
xml.send(JSON.stringify(obj));
}
});
</script>
</body>
</html>