1.中间件分类

应用程序级别中间件

        通过 app.use() 或 app.METHOD()(如 app.get)绑定的中间件,作用于整个应用程序。例如

记录请求日志、解析请求体等全局功能。例如:

app.use((req, res, next) => {console.log('Request URL:', req.url);next();
});
路由级别中间件

        绑定到 router.use() 或 router.METHOD() 的中间件,仅对特定路由生效。常用于分组路由的

共享逻辑(如权限校验)。例如:

const router = express.Router();
router.use((req, res, next) => {if (req.user.isAdmin) next();else res.status(403).send('Forbidden');
});
错误处理中间件

        接收四个参数 (err, req, res, next),用于捕获并处理同步/异步错误。需定义在中间件链

末尾。例如:

app.use((err, req, res, next) => {console.error(err.stack);res.status(500).send('Server Error');
});
内置中间件

Express 提供的开箱即用功能,如 express.json() 解析 JSON 请求体:

app.use(express.json());
第三方中间件

通过 npm 安装的中间件,例如 cors 处理跨域、helmet 增强安全性:

app.use(require('cors')());

2.中间件的使用

app.js文件中:

const express = require("express");const app = express();
const routerIndex=require("./router/index")
const videoRouter=require("./router/vedio")
const PORT = process.env.PORT || 3000;// 设置日志中间件 中间件代码的位置很有讲究 必须是所有路由的前面才行
app.use((req, res, next) => {console.log(`${req.method} ${req.url},${Date.now()}`);// 继续处理下一个中间件或路由处理函数next();
},function(req, res, next) { console.log('输出了日志,然后就可以执行这里面的代码,可以写多个这样的函数,然后使用next()执行下一个函数');next();
});
// 当有四个参数时,会默认这是个错误处理中间件
app.use((err,req,res,next)=>{console.log(err,'错误信息');res.status(500).send("服务器错误")
})
// 挂载路由  所有的路由前面都要加 /api,相当于vue的反向代理
app.use('/api',routerIndex);
app.use('/vedio',videoRouter)
// 挂载统一处理服务端错误中间件
// app.use(errorHandler());// all 方法,可以处理 /xx 路径传过来的所有请求方法都可以触发,不管时get、post、put请求都会触发它
app.all('/xx',(req,res)=>{res.send('xx')
})app.listen(PORT, () => {console.log(`Server is running at http://localhost:${PORT}`);
});

在app.js文件同级的router文件夹下的index.js:

const express = require('express')const router = express.Router()router.get('/',(req,res)=>{console.log(req.method);res.send('/index')
})
router.get('/users',(req,res)=>{console.log(req.method);res.send('/users')
})module.exports = router

在app.js文件同级的router文件夹下的vedio.js:

const express =require('express')
const router=express.Router()
// 这里的路由不是前端的跳转页面路由,而是后端的接口路由路径
router.get('/list',(req,res)=>{console.log('list');res.send('list')
})
module.exports=router

3.路由

// 可以匹配正则,/us+er表示匹配多个s叠加的路径,比如/usser、/ussser
app.get('/us+er',(req,res)=>{res.send(`${req.method} ${req.url}`)
})

获取路由参数:

router.get('/list/:id',(req,res)=>{// 获取路由参数console.log(req.params.id);res.send('list')
})

还可以链式调用:

router.get('/list/:id/are/:age',(req,res)=>{// 获取路由参数console.log(req.params.id);  // {id:2,age:3}res.send('list')
})
.post('/vedio',(req,res)=>{res.send('list')
})

使用res.render渲染:

// app.js文件
const express = require("express");
const app = express();
const path = require('path');
// 设置模板引擎(以 EJS 为例)
app.set('view engine', 'ejs');
// 设置视图文件目录
app.set('views', path.join(__dirname, 'views'));
const routerIndex=require("./router/index")
// 所有的路由前面都要加 /api,相当于vue的反向代理
app.use('/api',routerIndex);// router/index.js文件
const express = require('express')
const router = express.Router()
router.get('/',(req,res)=>{console.log(req.method);// res.render 是服务器端渲染,页面跳转到views/test/index.html页面中 res.render('test/index', { name: 'Express 路由1' });// res.send('/index')
})
module.exports = router// views/test/index.ejs文件
<!DOCTYPE html>
<html lang="zh-CN"><head><metaname="viewport"content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title><%= name %></title></head><body><h1>Hello, <%= name %></h1></body><script>function corsGetData() {alert("dsafdsafdsafsda");}</script>
</html>// 安装ejs
npm install ejs

效果:(请求 http://127.0.0.1:3000/api/ 直接渲染页面)

其他的响应方法:

// 这里的路由不是前端的跳转页面路由,而是后端的接口路由路径
router.get('/list/:id',(req,res)=>{// 获取路由参数console.log(req.params.id);// 下载文件  提示客户端下载文件res.download('./files/report.pdf')// 结束响应过程  不发送任何数据,直接结束响应// 通常用于简单响应或与 res.write() 配合使用res.end()// 发送 JSON 格式的响应 自动设置 Content-Type 为 application/jsonres.json({ message: 'Hello World' })// 重定向到指定的 URL  默认发送 302 状态码res.redirect('/login')// 渲染模板引擎视图res.render('index.ejs', { title: '首页' })// res.render 是服务器端渲染,页面跳转到views/test/index.html页面中 res.render('test/index', { name: 'Express 路由1' });// 发送文件作为响应res.sendFile('/views/index.html')// 设置响应状态码并发送其字符串表示作为响应体res.sendStatus(404) // 会发送 404 状态码和 "Not Found" 字符串res.send('list')
})

4. 设置跨域和记录日志

// 跨域
npm i cors
// 请求日志中间件
npm i morgan

在app.js文件中:

const cors =require('cors')
const morgan =require('morgan')
app.use(cors())
app.use(morgan('dev'))// 只记录开发时的日志

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/92598.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/92598.shtml
英文地址,请注明出处:http://en.pswp.cn/web/92598.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Dokcer创建中间件环境

简而言之&#xff0c;用docker来搞中间件环境比价好使&#xff0c;不用关心各种环境了 rabbitmqsudo docker run -d \--name rabbitmq \-p 5672:5672 \-p 15672:15672 \rabbitmq:3.8-managementredis 5.0.3 docker start my-redisdocker run --name my-redis -d -p 6379:6379 \…

Linux高级编程-文件操作

1.Linux下的文件类型7种文件类型&#xff1a;b 块设备文件 -------> 存储类设备&#xff08;硬盘&#xff09; c 字符设备文件 ------->如输入输出设备&#xff08;鼠标键盘显示器...&#xff09; d 目录文件 ------->文件夹 - 普通文件 -------&g…

web:vue中import *** from 和import {***} from的区别

在Vue.js中,import语句用于导入模块、组件或变量等。使用带花括号{}和不带花括号的区别主要在于导入的内容是具名导出(named exports)还是默认导出(default export)。 默认导入 (Default Import) - 不带花括号 import Vue from vue; import MyComponent from ./MyCompone…

Mysql如何优化my.conf配置文件?

优化 MySQL 的 my.cnf 配置文件&#xff0c;可以显著提升数据库性能&#xff0c;特别是在高并发或大数据量场景下。以下是优化 my.cnf 的方法和建议&#xff0c;涵盖 常见配置项、参数说明 和 优化技巧。1. 优化前的准备工作在修改 my.cnf 之前&#xff0c;需了解以下内容&…

Cherryusb UAC例程对接STM32内置ADC和DAC播放音乐和录音(上)=>TIM+DAC+ADC+DMA正弦波回环测试

0. 概述 文本目标基于Cherryusb官方例程audio_v1_mic_speaker_multichan_template.c&#xff0c;底层对接STM32的内置ADC和DAC&#xff0c;实现录音和播放。通过电脑播放歌曲&#xff0c;板子发出声音。通过电脑录音机开启录音&#xff0c;板子作为麦克风采集声音&#xff0c;…

数模个人笔记

写在前面&#xff1a;不建议观看&#xff0c;会烂尾的1.马氏链&#xff1a;状态空间指的是随机变量的取值范围&#xff0c;xi称为一个状态&#xff0c;应用背景在现在的条件下下一状态发生的概率&#xff0c;比如退火&#xff0c;他的条件概率可化简为&#xff1a;且nm时刻的概…

Spring Boot自定义Starter:从原理到实战全解析

1. 背景与需求1.1 什么是Starter&#xff1f; Spring Boot的起步依赖&#xff08;Starter&#xff09;是一种特殊的依赖描述符&#xff0c;用于简化Spring应用的依赖管理和自动配置。官方文档将Starter定义为“一组方便的依赖描述符”&#xff0c;开发者只需引入对应的Starter&…

安宝特方案丨工业AR+AI质检方案:致力于提升检测精度与流程效率

据IDC预测&#xff0c;2025年中国工业AI质检市场规模将达62亿元&#xff0c;年复合增长率28.5%&#xff0c;新能源、消费电子、高端装备三大领域贡献超70%市场份额。这一数据印证了AI质检已从可选技术升级为制造业降本增效的生存刚需。当前制造业质检环节正面临&#xff1a;精度…

AudioLLM

参考链接&#xff1a;https://mp.weixin.qq.com/s/cscrUn7n_o6PdeQRzWpx8g 视频教程&#xff1a;https://www.bilibili.com/video/BV1LGbozkEDY 模型代码&#xff1a;https://github.com/boson-ai/higgs-audio 如果是两个模型加在一起&#xff1a;一个语言模型&#xff0c;一个…

基于 CEP 引擎的算法拆单与调度实践—基础篇

在金融市场中&#xff0c;大额订单的一次性交易可能会对市场价格产生较大冲击&#xff0c;导致交易成本增加。例如&#xff0c;大额买入订单可能会迅速推高股价&#xff0c;使后续买入成本上升&#xff1b;大额卖出订单则可能打压股价&#xff0c;造成资产贱卖。拆单算法通过将…

开源 C# TCP 通信框架 SocketDJ 发布:轻量、免费、可扩展

前言市面上的网络通信框架琳琅满目&#xff0c;功能强大者有之&#xff0c;但不少都存在功能闭源、商业收费、学习成本高等问题。作为一名热爱底层技术的开发者&#xff0c;我始终相信&#xff1a;基础通信能力应当简单、透明且免费。最近正好有项目需求&#xff0c;索性动手从…

移动机器人路径规划中ROS2中间件性能的研究综述

导读&#xff1a; 随着移动机器人在工业自动化、特种作业及智能服务领域的广泛应用&#xff0c;其路径规划能力越来越依赖机器人操作系统ROS2的通信性能。ROS2通过去中心化架构与数据分发服务中间件显著提升了系统可靠性&#xff0c;但动态复杂环境中路径规划对通信延迟、带宽…

【昇腾】Atlas 500 A2 智能小站制卡从M.2 SATA盘启动Ubuntu22.04系统,重新上电卡死没进系统问题处理_20250808

一、问题背景 Atlas 500 A2智能小站是华为基于20T 12G版本的Atlas 200I A2加速模块开发的面向广泛边缘应用场景的轻量边缘设备&#xff0c;具有超强计算性能、配置灵活、体积小、支持温度范围宽、环境适应性强、易于维护 管理等特点的产品。Atlas 500 A2智能小站主要应用在智能…

sigaction 中 sa_handler = SIG_IGN 的深度解析与应用实践

sigaction 中 sa_handler SIG_IGN 的深度解析与应用实践 核心意义&#xff1a;主动忽略信号 当 sa_handler 设置为 SIG_IGN 时&#xff0c;内核将完全丢弃指定的信号&#xff0c;不会&#xff1a; 执行默认行为调用任何处理函数中断进程的正常执行 这与 SIG_DFL&#xff08;默…

【LLM实战|langchain、qwen_agent】RAG高级

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?type=blog 0. 前言 RAG高级 1. RAG 高效召回方法 合理设置TOP-K 改进索引算法 -知识图谱 引入重排序 重排序模型 BGE-Rerank Cohere Rerank 混合检索 向量索引+关键词索引…

C++方向知识汇总(一)

关于单例模式1.什么是单例模式&#xff1f;答&#xff1a;单例模式是一种创建型设计模式&#xff0c;确保一个类在运行期间仅有一个实例&#xff0c;提供全局唯一的访问点2.单例模式的目的&#xff1f;答&#xff1a;避免重复创建资源消耗大的对象&#xff0c;例如日志系统、线…

学习:JS[8]本地存储+正则表达式

一.本地存储1.介绍将数据存储到用户浏览器当中设置、读取方便、页面刷新不丢失数据2.本地存储分类-localStoragea.语法(1)存储数据//存储数据 localStorage.setItem(键,值)如 localStorage.setItem(uname,哈哈)(2)获取数据//获取方式 都加引号 localStorage.getItem(键) localS…

C++算法练习:单词识别

做题记录&#xff1a;牛客习题&#xff1a;单词识别 相关题目代码已经提交到gitee中&#xff1a;楼田莉子 (riko-lou-tian) - Gitee.com喜欢请点个赞谢谢 目录 题目&#xff1a; C 字符函数头文件头文件&#xff1a;&#xff08;C 标准库&#xff09;核心函数功能说明&#…

从免费到盈利:Coze智能体1小时封装变现全流程指南——井云科技

在AI技术普惠的浪潮下&#xff0c;Coze等智能体平台让零代码开发者也能快速构建功能强大的AI助手。然而&#xff0c;许多创作者在完成智能体开发后&#xff0c;却面临“工具免费、成本自担”的困境——用户无限制调用导致算力成本飙升&#xff0c;想收费又缺乏成熟的支付与用户…

C++学习之STL学习:map/set

通过前面的学习&#xff0c;我们已经对C STL有了初步了解。然而&#xff0c;STL作为一个庞大复杂的体系&#xff0c;远不止这些内容。接下来&#xff0c;我们将深入探讨STL中的另外两个重要组件——map和set。 作者的个人gitee&#xff1a;楼田莉子 (riko-lou-tian) - Gitee.co…