NodeJS全栈开发面试题讲解——P2Express / Nest 后端开发

news2025/6/4 15:50:50

2.1 Express 的中间件机制?如何组织一个 RESTful API 项目?

面试官好,我来讲讲 Express 的中间件机制,它是 Express 架构的核心,也是组织 RESTful 项目的基础。

🧩 什么是中间件?

中间件(Middleware)就是一类函数,它们可以对 reqres 进行加工、拦截、判断,决定是否将请求传递给下一个处理函数。

✨ 形式:

function (req, res, next) { ... }

  • req:请求对象;

  • res:响应对象;

  • next():调用下一个中间件。

🧱 中间件执行顺序是按注册顺序的:

app.use(logger);
app.use(auth);
app.get('/user', controller);

📦 常见中间件分类:

类型示例
应用级app.use() 全局中间件
路由级router.use()、局部中间件
错误处理中间件4 个参数 (err, req, res, next)
内置中间件express.json()static()
第三方中间件corsbody-parsermorgan


📐 如何组织一个 RESTful 项目?

文件结构推荐:

src/
├── routes/
│   └── user.js
├── controllers/
│   └── userController.js
├── middlewares/
│   └── auth.js
├── services/
│   └── userService.js
├── utils/
├── app.js

核心思想:路由-控制器-服务分离,中间件集中注册。

// routes/user.js
const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');
const auth = require('../middlewares/auth');

router.get('/profile', auth, userController.getProfile);
module.exports = router;

2.2 如何处理接口异常?如何做统一异常拦截?

在 Express 和 NestJS 中,我分别有两种做法来实现“统一异常处理”,这对于生产级项目来说是必不可少的。

✅ Express:统一异常处理

Express 中通过定义 错误处理中间件 来统一拦截异常。

// app.js
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ code: 500, message: 'Internal Server Error' });
});

在路由/服务中使用 next(err) 触发:

try {
  throw new Error('DB Error');
} catch (err) {
  next(err);
}

✅ NestJS:内置异常过滤器机制

NestJS 提供 @Catch() 装饰器,可以创建自定义异常过滤器。

// common/filters/http-exception.filter.ts
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const res = ctx.getResponse<Response>();
    const status = exception.getStatus();

    res.status(status).json({
      statusCode: status,
      message: exception.message,
      timestamp: new Date().toISOString(),
    });
  }
}

注册方式:

// main.ts
app.useGlobalFilters(new HttpExceptionFilter());

2.3 JWT 鉴权的完整流程?Token 存储在哪里最安全?

我来详细说明一个完整的 JWT 登录鉴权流程,以及 token 应该如何存储最安全。

🔐 JWT 基本结构:

JWT 分为三段:

Header.Payload.Signature

  • Header:加密算法

  • Payload:用户数据(如 userId, role)

  • Signature:签名,防篡改


✅ JWT 鉴权流程:

  1. 用户登录时提交用户名 + 密码;

  2. 服务端验证后,使用 jsonwebtoken 生成 Token:

const token = jwt.sign({ userId: 123 }, secret, { expiresIn: '1h' });

  1. 客户端收到后,将 Token 储存并在后续请求中带上:

Authorization: Bearer <token>

  1. 服务端中间件负责解析、验证 Token 并附加用户信息:

const decoded = jwt.verify(token, secret);
req.user = decoded;

✅ Token 存储方案对比:

存储位置安全性建议使用场景
LocalStorage易被 XSS 获取适合开发调试、测试环境
Cookie(HttpOnly)安全、防 XSS✅ 最安全,推荐生产环境
SessionStorage随刷新丢失不适合长期登录会话


2.4 如何实现接口的权限控制?支持不同角色访问不同资源?

我习惯使用“路由权限 + 用户角色”的结合方式来实现精细化权限控制。

🎯 实现思路:

  1. 登录时,在 JWT 中记录用户的 rolepermissions

  2. 使用中间件或守卫(Guard)读取用户角色,匹配当前路由所需权限;

  3. 不满足则返回 403 Forbidden。


✅ Express 示例:

function roleGuard(roles) {
  return (req, res, next) => {
    const userRole = req.user.role;
    if (roles.includes(userRole)) next();
    else res.status(403).json({ message: 'Forbidden' });
  };
}

router.get('/admin', auth, roleGuard(['admin']), adminController.doSomething);

✅ NestJS 示例(守卫 + 装饰器):

// roles.decorator.ts
export const Roles = (...roles: string[]) => SetMetadata('roles', roles);

// roles.guard.ts
@Injectable()
export class RolesGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const roles = this.reflector.get<string[]>('roles', context.getHandler());
    const user = context.switchToHttp().getRequest().user;
    return roles.includes(user.role);
  }
}

使用:

@UseGuards(RolesGuard)
@Roles('admin')
@Get('/admin')
getAdminData() { ... }

2.5 如何在 NestJS 中使用装饰器、模块、依赖注入机制?

NestJS 的核心就是基于模块化的架构、装饰器驱动和依赖注入。我详细说明下。


✅ 模块(Module)

每个模块(@Module)组织了 controller、service、provider 的集合。

@Module({
  controllers: [UserController],
  providers: [UserService],
  exports: [UserService]
})
export class UserModule {}

✅ 控制器(Controller)

控制请求和响应,对应 RESTful 接口。

@Controller('user')
export class UserController {
  constructor(private readonly userService: UserService) {}

  @Get()
  findAll() {
    return this.userService.findAll();
  }
}

✅ 服务(Service)+ 依赖注入(DI)

@Injectable()
export class UserService {
  findAll() { return [{ name: 'Tom' }]; }
}

Service 是业务逻辑层,通过构造函数注入。

// Controller 中自动注入

constructor(private readonly userService: UserService) {}


✅ 自定义装饰器(Decorator)

用于封装通用逻辑,如读取 token 中用户 ID。

export const CurrentUser = createParamDecorator(
  (data, ctx: ExecutionContext) => {
    const request = ctx.switchToHttp().getRequest();
    return request.user;
  },
);

使用:

@Get('/profile')
getProfile(@CurrentUser() user) {
  return user;
}

✅ 总结对照表:

问题技术点
2.1Express 中间件机制、项目结构设计
2.2错误处理中间件 vs Nest 异常过滤器
2.3JWT 鉴权流程、Token 安全存储
2.4RBAC 角色权限控制实现方式
2.5Nest 模块系统、依赖注入、装饰器应用


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

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

相关文章

从线性代数到线性回归——机器学习视角

真正不懂数学就能理解机器学习其实是个神话。我认为&#xff0c;AI 在商业世界可以不懂数学甚至不懂编程也能应用&#xff0c;但对于技术人员来说&#xff0c;一些基础数学是必须的。本文收集了我认为理解学习本质所必需的数学基础&#xff0c;至少在概念层面要掌握。毕竟&…

计算机网络相关发展以及常见性能指标

目录 一、因特网概述 1.1 基本概念 1.2 因特网发展的三个阶段 1.3 英特网服务提供者ISP 1.4 英特网的标准化工作 1.5 因特网的组成 1.6 简单总结 二、3种交换方式 2.1 电路交换&#xff08;Circuit Switching&#xff09; 2.2 分组交换&#xff08;Packet Switching&…

通义灵码:基于MCP的火车票小助手系统全流程设计与技术总结

具体操作步骤请访问&#xff1a;https://blog.csdn.net/ailuloo/article/details/148319336?spm1001.2014.3001.5502 前沿技术应用全景图 一、项目背景与需求分析 目标&#xff1a;基于12306 MCP接口&#xff0c;开发一款解决高峰出行&#xff08;春运/节假日&#xff09;痛…

为什么建立 TCP 连接时,初始序列号不固定?

主要原因有两个方面&#xff1a; 很大程度上避免历史报文被下一个相同四元组的 TCP 连接接收问题&#xff08;主要方面&#xff09;防止黑客伪造相同序列号的 TCP 报文被接收 接下来&#xff0c;详细说说第一点 假设每次建立 TCP 连接时&#xff0c;客户端和服务端的初始序列…

VBA数据库解决方案二十:Select表达式From区域Where条件Order by

《VBA数据库解决方案》教程&#xff08;版权10090845&#xff09;是我推出的第二套教程&#xff0c;目前已经是第二版修订了。这套教程定位于中级&#xff0c;是学完字典后的另一个专题讲解。数据库是数据处理的利器&#xff0c;教程中详细介绍了利用ADO连接ACCDB和EXCEL的方法…

NX753NX756美光科技闪存NX784NX785

技术解读与产品特性 美光科技的NX系列闪存&#xff0c;包括NX753、NX756、NX784、NX785等型号&#xff0c;代表了当前存储技术的前沿水平。这些产品基于先进的NAND闪存技术&#xff0c;采用业界领先的3D TLC NAND技术&#xff0c;实现了高速的数据读写能力。3D TLC NAND技术通…

使用 pytesseract 构建一个简单 OCR demo

简介 pytesseract 库是 Google Tesseract OCR &#xff08;光学字符识别&#xff09;引擎的一个 Python 封装库&#xff0c;使用广泛且功能强大。 构建 使用 pytesseract 构建一个简单 OCR demo。 步骤一&#xff1a;安装必要的库 您需要在您的 Python 环境中安装 pytessera…

git 如何解决分支合并冲突(VS code可视化解决+gitLab网页解决)

1、定义&#xff1a;两个分支修改了同一文件的同一行代码&#xff0c;无法自动决定如何合并代码&#xff0c;需要人工干预的情况。&#xff08;假设A提交了文件a,此时B在未拉取代码的情况下&#xff0c;直接提交是会报错的&#xff0c;此时需要拉取之后再提交才会成功&#xff…

【CF】Day72——Codeforces Round 890 (Div. 2) CDE1 (二分答案 | 交互 + 分治 | ⭐树上背包)

C. To Become Max 题目&#xff1a; 思路&#xff1a; 二分挺好想的&#xff0c;但是check有点不好写 看到最大值&#xff0c;试试二分&#xff0c;如果 x 可以&#xff0c;那么 x - 1 肯定也可以&#xff0c;所以具有单调性&#xff0c;考虑二分 如何check呢&#xff1f;由于…

单片机寄存器的四种主要类型!

1. 控制寄存器&#xff08;Control Registers&#xff09;​​ ​​专业定义​​&#xff1a;用于配置硬件行为或触发操作的寄存器。 ​​大白话​​&#xff1a; 相当于设备的​​“控制面板”​​&#xff0c;通过写入特定值来​​开关功能​​或​​调整参数​​。例如&am…

智能嗅探AJAX触发:机器学习在动态渲染中的创新应用

一、问题描述&#xff1a;数据加载变“隐形”&#xff0c;采集举步维艰 随着Web技术不断发展&#xff0c;越来越多网站采用了AJAX、动态渲染等技术来加载数据。以今日头条&#xff08;https://www.toutiao.com&#xff09;为例&#xff0c;用户打开网页时并不会一次性加载所有…

【计算机网络】Linux下简单的UDP服务器(超详细)

套接字接口 我们把服务器封装成一个类&#xff0c;当我们定义出一个服务器对象后需要马上初始化服务器&#xff0c;而初始化服务器需要做的第一件事就是创建套接字。 &#x1f30e;socket函数 这是Linux中创建套接字的系统调用,函数原型如下: int socket(int domain, int typ…

华为OD机试真题——报文回路(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳实现

2025 A卷 100分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析; 本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分…

功能丰富的PDF处理免费软件推荐

软件介绍 今天给大家介绍一款超棒的PDF工具箱&#xff0c;它处理PDF文档的能力超强&#xff0c;而且是完全免费使用的&#xff0c;没有任何限制。 TinyTools&#xff08;PC&#xff09;这款软件&#xff0c;下载完成后即可直接打开使用。在使用过程中&#xff0c;操作完毕后&a…

Java补充(Java8新特性)(和IO都很重要)

一、Lambda表达式 1.1、为什么使用Lambda表达式 Lambda表达式起步案例 下面源码注释是传统写法&#xff0c;代码是简写表达式写法 import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.function.Consumer;/* * 学什么…

分布式流处理与消息传递——Kafka ISR(In-Sync Replicas)算法深度解析

Java Kafka ISR&#xff08;In-Sync Replicas&#xff09;算法深度解析 一、ISR核心原理 #mermaid-svg-OQtnaUGNQ9PMgbW0 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-OQtnaUGNQ9PMgbW0 .error-icon{fill:#55222…

OS10.【Linux】yum命令

目录 1.安装软件的几种方法 直接编译源代码,得到可执行程序 使用软件包管理器 2.yum yum list命令 参数解释 yum install命令 yum remove命令 下载链接存放的位置 扩展yum源 实验:安装sl小火车命令 sl命令的选项 方法1:man sl 方法2:读源代码 3.更新yum源 查看…

多模态大语言模型arxiv论文略读(102)

Chat2Layout: Interactive 3D Furniture Layout with a Multimodal LLM ➡️ 论文标题&#xff1a;Chat2Layout: Interactive 3D Furniture Layout with a Multimodal LLM ➡️ 论文作者&#xff1a;Can Wang, Hongliang Zhong, Menglei Chai, Mingming He, Dongdong Chen, Ji…

高端装备制造企业如何选择适配的项目管理系统提升项目执行效率?附选型案例

高端装备制造项目通常涉及多专业协同、长周期交付和高风险管控&#xff0c;因此系统需具备全生命周期管理能力。例如&#xff0c;北京奥博思公司出品的 PowerProject 项目管理系统就是一款非常适合制造企业使用的项目管理软件系统。 国内某大型半导体装备制造企业与奥博思软件达…

AI炼丹日志-22 - MCP 自动操作 Figma+Cursor 自动设计原型

MCP 基本介绍 官方地址&#xff1a; https://modelcontextprotocol.io/introduction “MCP 是一种开放协议&#xff0c;旨在标准化应用程序向大型语言模型&#xff08;LLM&#xff09;提供上下文的方式。可以把 MCP 想象成 AI 应用程序的 USB-C 接口。就像 USB-C 提供了一种…