1.9 Express

Express 是一个基于 Node.js 平台的轻量级、灵活的 Web 应用框架,它为构建 Web 应用和 API 提供了一系列强大的功能。

核心特性

  1. 中间件支持:Express 使用中间件(middleware)函数来处理 HTTP 请求和响应。中间件可以访问请求对象(req)、响应对象(res),以及应用程序的请求-响应循环中的下一个中间件函数。通过中间件,你可以执行各种任务,如日志记录、解析请求体、路由处理等。

  2. 路由:Express 提供了简洁而灵活的路由机制,允许你根据不同的 HTTP 方法(GET, POST 等)和 URL 路径定义处理逻辑。你可以创建复杂的路由结构,并且支持动态路由参数。

  3. 视图系统:Express 支持多种模板引擎,如 EJS、Pug、Handlebars 等,使得你可以轻松地生成 HTML 页面。

  4. 错误处理:内置错误处理机制,可以通过特定的中间件来捕获并处理应用中的错误。

  5. 与数据库集成:虽然 Express 本身不绑定任何数据库,但其灵活性意味着它可以轻松地与 MongoDB、MySQL、PostgreSQL 等数据库集成。

快速入门

安装 Express:

npm install express --save

创建一个简单的服务器:

const express = require('express');
const app = express();app.get('/', (req, res) => {res.send('Hello World!');
});app.listen(3000, () => {console.log('Server is running on port 3000.');
});

Express兼容原生http响应

Express 中,响应对象(res)是对 Node.js 原生 http.ServerResponse 对象的扩展,因此它兼容原生 HTTP 的响应方法。这意味着你可以使用原生的方法,也可以使用由 Express 提供的更高级的 API 来发送响应。

//原生 Node.js:
//使用 res.statusCode、res.setHeader、res.writeconst express = require('express');
const http = require('http');const app = express();// Express 中间件处理
app.use((req, res, next) => {// 原生 HTTP 响应方法示例res.statusCode = 200;res.setHeader('Content-Type', 'text/plain');res.write('Hello from Express with native HTTP!');// 继续 Express 流程next();
});// Express 路由处理
app.get('/', (req, res) => {// 可以继续使用 Express APIres.end(' (with Express finish)');
});app.listen(3000, () => {console.log('Server running on port 3000');
});

原生 Node.js: 需要手动设置状态码为 3xx 并设置 Location 头。

response.writeHead(302, {Location: 'http://example.com'});
response.end();

Express: 使用便捷的 .redirect() 方法。

res.redirect('http://example.com');

Express 提供了便捷的方法如 .download() 和直接使用流(Stream)来响应文件下载请求。

这是 Express 特有的方法,用于触发文件下载,并自动设置适当的响应头(如 Content-Disposition: attachment)。

const express = require('express');
const app = express();
const path = require('path');app.get('/download', (req, res) => {const filePath = path.join(__dirname, 'public', 'example.txt');res.download(filePath); // 自动触发下载
});

参数说明:

  • res.download(filePath, [filename], [options], [callback])
    • filePath: 文件在服务器上的路径。
    • [filename]: 客户端看到的文件名(可选,默认为原始文件名)。
    • [options]: 可选配置对象,例如 { headers: { ... } }
    • [callback]: 下载完成后的回调函数。

原生 http 的方法时,你需要手动控制所有流程,包括读取文件、设置响应头、发送数据等

// const http = require('http');
const fs = require('fs');
const path = require('path');
const express = require('express');const app = express();// const server = http.createServer((req, res) => {
//   if (req.url === '/download') {
//     const filePath = path.join(__dirname,  'example.txt');//     res.writeHead(200, {
//       'Content-Type': 'application/octet-stream',
//       'Content-Disposition': 'attachment; filename="example.txt"'
//     });//     const readStream = fs.createReadStream(filePath);
//     readStream.pipe(res);
//   } else {
//     res.writeHead(404);
//     res.end('Not Found');
//   }
// });// server.listen(3000, () => {
//   console.log('Server running on port 3000');
// });app.get('/download', (req, res) => {const filePath = path.join(__dirname,  'example.txt');res.writeHead(200, {'Content-Type': 'application/octet-stream','Content-Disposition': 'attachment; filename="example.txt"'});const readStream = fs.createReadStream(filePath);readStream.pipe(res);
});app.listen(3000, () => {console.log('Server running on port 3000');});

express 特有的响应客户端方法

res.send()

自动根据传入数据类型设置合适的响应头,并发送响应体。

  • 如果是字符串:默认设置 Content-Type: text/html
  • 如果是对象或数组:自动调用 JSON.stringify(),并设置 Content-Type: application/json
  • 支持 Buffer 数据(如二进制)
res.send('Hello World'); // 发送 HTML 或纯文本
res.send({ name: 'Tom' }); // 自动转为 JSON 并设置 Content-Type: application/json
res.send(Buffer.from('ABC')); // 发送二进制数据
  • 智能处理不同类型的数据。
  • 不会触发浏览器下载行为。
  • 适合返回 API 响应、HTML 页面等。

res.json()

专门用于发送 JSON 格式的数据,自动调用 JSON.stringify() 并设置 Content-Type: application/json

res.json({ success: true, data: { id: 1 } });
// 输出:
// {"success":true,"data":{"id":1}}
  • 保证响应内容为标准 JSON 格式。

  • 设置正确的 Content-Type
  • 推荐用于构建 RESTful API。

⚠️ 注意:如果传入的是一个循环引用的对象,json() 会抛出错误。


res.sendFile()

用于发送一个文件给客户端(例如 HTML 文件、图片等),常用于静态资源服务。

const path = require('path');app.get('/', (req, res) => {res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
  • 必须传入文件的绝对路径(推荐使用 path.join() 构造)。

  • 自动设置适当的 MIME 类型(如 text/htmlimage/png 等)。
  • 不会强制浏览器下载,而是尝试在浏览器中直接显示(如 PDF、图片等)。
 res.status(code)
  • 用途:设置 HTTP 状态码。通常与其他响应方法链式使用。
  • res.status(404).send('Not Found');
 res.set(field [, value]) 或 res.header(field [, value])
  • 用途:设置 HTTP 响应头。
  • res.set('Content-Type', 'text/plain');
    // 或者
    res.set({'Content-Type': 'text/plain','ETag': '12345'
    });
 res.type(type) 或 res.contentType(type)
  • 用途:设置 Content-Type 响应头。type 参数可以是 MIME 类型或文件扩展名。
  • res.type('.html'); // Content-Type 设置为 text/html
    res.type('json'); // Content-Type 设置为 application/json

路由(Routing)

处理不同路径和 HTTP 方法的请求。

基本路由
// GET 请求
app.get('/users', (req, res) => { /* ... */ });// POST 请求
app.post('/users', (req, res) => { /* ... */ });// 动态路由参数
app.get('/users/:id', (req, res) => {const userId = req.params.id;res.send(`User ${userId}`);
});
路由分组

使用 express.Router 创建模块化路由:

// routes/users.js
const router = require('express').Router();router.get('/', (req, res) => { /* 获取所有用户 */ });
router.post('/', (req, res) => { /* 创建用户 */ });module.exports = router;// main.js
const userRoutes = require('./routes/users');
app.use('/api/users', userRoutes);

 中间件(Middleware)

Express 中,中间件是处理 HTTP 请求的核心机制,它允许你在请求到达路由处理函数之前或之后执行代码。中间件函数可以:

  1. 修改请求和响应对象(如添加属性、设置头部)
  2. 结束请求 - 响应循环(如返回错误或结果)
  3. 调用下一个中间件函数(通过 next()

内置中间件

// 解析 JSON 请求体
app.use(express.json());// 静态文件服务
app.use(express.static('public'));//有时你可能希望为静态文件添加一个路径前缀,可以通过将挂载点作为第一个参数传递给 express.static 实现:
app.use('/static', express.static('public'));
// 现在,你需要通过 /static/example.html 来访问 public 目录下的 example.html 文件//默认情况下,如果 express.static 找不到请求的文件,它不会发送下一个中间件。如果你想改变这种行为,可以让它继续执行后续的中间件:app.use(express.static('public', { fallthrough: true }));app.use((req, res, next) => {res.status(404).send('Sorry, we cannot find that!');
});
// 这将确保当静态文件未找到时,仍然有机会返回自定义的 404 页面或其他内容。

自定义中间件

中间件函数接收三个参数:(req, res, next)

  • req:HTTP 请求对象
  • res:HTTP 响应对象
  • next:指向下一个中间件的函数,必须调用它才能继续执行后续中间件
// 日志中间件
app.use((req, res, next) => {console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);next(); // 传递控制权给下一个中间件
});// 错误处理中间件(必须有 4 个参数)
app.use((err, req, res, next) => {console.error(err);res.status(500).send('Internal Server Error');
});

中间件的类型

1. 应用级中间件

绑定到 app 实例,处理所有路由请求:

// 记录所有请求的时间戳
app.use((req, res, next) => {req.requestTime = Date.now();next();
});
2. 路由级中间件

绑定到特定路由,只处理匹配的请求:

// 仅处理 /users 路径的请求
app.use('/users', (req, res, next) => {console.log('Processing user-related request');next();
});

3. 错误处理中间件

接收四个参数 (err, req, res, next),用于捕获和处理错误:

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

错误处理

错误处理中间件与普通中间件类似,但需要四个参数,其签名如下:(err, req, res, next)。即使你不使用 next 参数,也必须指定它,以便 Express 能够识别这是一个错误处理中间件。

统一处理应用中的异常:


app.get('/users',(req, res) => {try {const data = getData();req.data = data;next();} catch (err) {next(err); // 将错误传递给错误处理中间件}
});// 全局错误处理
app.use((err, req, res, next) => {const statusCode = err.statusCode || 500;res.status(statusCode).json({error: {message: err.message,status: statusCode}});
});

关键点解释

  1. 触发错误:在任何地方调用 next() 并传入一个错误对象,就可以将控制权交给第一个匹配的错误处理中间件。
  2. 错误处理中间件:使用 app.use() 来定义,它会捕捉所有通过 next(err) 传递过来的错误。
  3. 环境变量判断:在这个例子中,根据应用程序环境(development 或 production),决定是否向客户端暴露详细的错误信息。这有助于保护生产环境下的敏感信息泄露。

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

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

相关文章

面壁智能MiniCPM4.0技术架构与应用场景

📋 目录 1. 引言:端侧智能新时代2. MiniCPM4.0概述3. 核心技术架构 3.1 高效双频换挡机制3.2 稀疏注意力机制3.3 系统级优化创新 4. 技术突破与性能表现5. 应用场景深度解析 5.1 智能手机应用5.2 智能家居场景5.3 汽车智能化5.4 其他端侧应用 6. 行业影…

RabbitMQ路由核心解密:从Exchange到RoutingKey的深度实践与避坑指南

🔍 RabbitMQ路由核心解密:从Exchange到RoutingKey的深度实践与避坑指南 “消息去哪了?”——这是每位RabbitMQ使用者在调试时最常发出的灵魂拷问。 理解Exchange与RoutingKey的协作机制,正是解开路由谜题的关键钥匙。 一、Exchang…

Spring MVC完全指南 - 从入门到精通

目录 1. Spring MVC简介 2. MVC架构模式 3. Spring MVC核心组件 4. 请求处理流程 5. 控制器详解 6. 请求映射 7. 参数绑定 8. 数据验证 9. 视图解析器 10. 模型数据处理 11. 异常处理 12. 拦截器 13. 文件上传下载 14. RESTful API 15. 配置详解 总结 1. Sprin…

实战使用docker compose 搭建 Redis 主从复制集群

文章目录 前言技术积累1、Redis 主从复制机制2、Docker Compose 编排3、 Redis 配置文件定制4、 验证主从状态5、 自动化部署与维护 环境准备实战演示创建redis目录及配置1、创建redis目录2、创建redis配置文件 启动redis集群服务1、创建docker-compose编排文件2、编排docker-c…

【学习笔记】RTSP-Ovnif-GB28181

【学习笔记】RTSP-Ovnif-GB28181 一、RTSP_RTP_RTCP RTSP(Real Time Streaming Protocol),RFC2326,实时流传输协议,是TCP/IP协议体系中的一个应用层协议。 RTP协议详细说明了在互联网上传递音频和视频的标准数据包格…

stm32-c8t6实现语音识别(LD3320)

目录 LD3320介绍: 功能引脚 主要特色功能 通信协议 端口信息 开发流程 stm32c8t6代码 LD3320驱动代码: LD3320介绍: 内置单声道mono 16-bit A/D 模数转换内置双声道stereo 16-bit D/A 数模转换内置 20mW 双声道耳机放大器输出内置 5…

RAG技术全解析:从概念到实践,构建高效语义检索系统——嵌入模型与向量数据库搭建指南

一、RAG技术概述:为什么需要RAG? 1.1 什么是RAG? RAG(Retrieval-Augmented Generation)是一种结合检索与生成能力的AI架构。其核心思想是通过外部知识库动态增强大语言模型(LLM)的生成能力&…

【资源分享】手机玩转经典游戏!小鸡模拟器1.9.0:PSP/NDS/GBA完美运行!

阿灿今天给大家推荐一款小鸡模拟器,这是一个老款PC和掌上游戏机模拟器。完美模拟街机(fbamamemameplus).PS、PSP、FC(NES)SFC(SNES)、GBA、GBC、MD、NDS、DC、NGP、WS (WSC) PCE、ONS 等18款经典掌机游戏机。小鸡模拟器同时也提供海量热门的汉化版游戏免…

matlab脉冲信号并绘制波形2025.6.11

以下是一个使用MATLAB生成5V、10MHz脉冲信号并绘制波形的示例代码: % 5V 10MHz脉冲信号仿真 clc; clear; close all; % 参数设置 voltage = 5; % 信号幅度(V) frequency = 10e6; % 脉冲频率(10MHz) duty_cycle =

ElasticJob初探

依赖版本 JDK版本是&#xff1a;jdk17 springboot版本 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.4</version></parent>zookeeper elasticjo…

【Vue3】(三)vue3中的pinia状态管理、组件通信方式及总结、插槽

目录 一、vue3的pinia 1、什么是pinia&#xff1f; 2、为什么Vue3选择pinia&#xff1f; 3、使用pinia的好处 4、安装pinia 2、项目配置 3、存储/读取pinia中的数据 4、修改pinia中的数据 5、storeToRefs&#xff08;保持store中数据的响应式&#xff09; 6、getters 7、…

WEB3全栈开发——面试专业技能点P1Node.js / Web3.js / Ethers.js

一、Node.js 事件循环 Node.js 的事件循环&#xff08;Event Loop&#xff09;是其异步编程的核心机制&#xff0c;它使得 Node.js 可以在单线程中实现非阻塞 I/O 操作。 &#x1f501; 简要原理 Node.js 是基于 libuv 实现的&#xff0c;它使用事件循环来处理非阻塞操作。事件…

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…

web架构4------(nginx常用变量,nginx中英文自动匹配,lnmp网站架构,正向代理,反向代理,负载均衡)

一.前言 本期来介绍nginx最后几个知识点&#xff0c;看着要说的内容很多&#xff0c;其实一点也不多&#xff0c;都是所见即所得的东西。 二.nginx常用变量 2.1 常用变量 $args 请求中的参数&#xff0c;也叫查询参数&#xff0c;如www.123.com/1.php?a1&b2的$args就是…

openeuler系统(CentOs)图形化桌面黑屏/丢失(开启VNC服务冲突)

1. VNC服务开启如下&#xff1a; https://zhuanlan.zhihu.com/p/5049263261 在centos8系统上使用tigervnc-server搭建VNC_centos8 tigervnc-server-CSDN博客 2. 上述操作完成后&#xff0c;连接VNC仍会出现黑屏&#xff0c;则需要编辑/root/.vnc/xstartup&#xff1a; [运维…

MySQL:Prepared Statement 预处理语句

预处理语句&#xff08;Prepared Statements&#xff09;是 MySQL 中一种用于执行 SQL 查询的高效、安全的方法。通过使用预处理语句&#xff0c;可以显著提升查询性能&#xff0c;并防止 SQL 注入攻击。本文将详细介绍 MySQL 预处理语句的概念、使用方法及其优势。 一、预处理…

EPPLUS——CAD c#读写EXCEL的第三方库

EPPLUS(可支持NET35) 在 CAD 的 C# 二次开发中&#xff0c;使用 EPPLUS 库处理 Excel 文件具有以下显著优点&#xff0c;尤其在兼容性、便捷性和性能等方面契合 CAD 项目的需求&#xff1a; 1. 跨.NET 版本兼容性强&#xff0c;适配 CAD 多环境部署 多框架支持&#xff1a;EP…

Linux知识回顾总结----进程状态

本章将会介绍进程的一些概念&#xff1a;冯诺伊曼体系结构、进程是什么&#xff0c;怎么用、怎么表现得、进程空间地址、物理地址、虚拟地址、为什么存在进程空间地址、如何感性得去理解进程空间地址、环境变量是如何使用的。 目录 1. 冯诺伊曼体系结构 1.1 是什么 1.2 结论 …

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…

Android Test3 获取的ANDROID_ID值不同

Android Test3 获取的ANDROID_ID值不同 这篇文章来说明上一篇文章中说到的一个现象&#xff1a;在同一个项目中&#xff0c;创建不同的 app module&#xff0c;运行同一段测试代码&#xff0c;获取到的 ANDROID_ID 的值不同。 我也是第一次认真研究这个现象&#xff0c;这个还…