Skip to content

NestJS 知识体系导图

一、NestJS 基础认知(入门要点)

1. NestJS 是什么

  • 基于 Node.js + TypeScript 的企业级后端框架,专为大型项目设计,兼顾规范与可扩展性

  • 底层依赖:默认基于 Express,可切换为 Fastify(性能更优)

  • 核心架构思想:模块化、分层架构、依赖注入(DI)、面向装饰器(AOP)

  • 设计理念:结构化、强类型、可测试、可扩展、规范统一,解决Express/Koa无规范、难维护的痛点

  • 与Express/Koa对比(要点对照):

    • Express:灵活自由、轻量,但无强制规范、弱类型,大型项目易混乱难维护

    • Koa:基于洋葱模型,异步处理优雅,但仍无强制分层,需手动搭建架构

    • NestJS:TS原生支持、强制分层架构、内置DI和AOP,生态完善,适合企业级后端开发

2. NestJS 核心优势(建议熟悉)

  • TS原生集成,类型安全,与前端TS技术栈完全统一,降低前后端协作成本

  • 强制分层架构(Controller/Service/Repository等),代码规范,便于团队协作和后期维护

  • 依赖注入(DI)机制,实现代码解耦,易于单元测试和功能替换

  • 支持AOP面向切面编程,通过拦截器、过滤器、守卫、管道实现统一处理,减少重复代码

  • 模块化架构,支持按业务拆分模块(用户、权限、商品等),可扩展至微服务、网关等场景

  • 内置完整生态:ORM集成(TypeORM)、参数校验、异常处理、认证授权等,无需额外手动集成

二、NestJS 核心架构(进阶重点)

1. 五大核心分层结构(常见)

  • Controller 控制器(请求入口)

    • 核心职责:接收HTTP请求、解析请求参数、路由分发、返回响应,不编写任何业务逻辑

    • 核心装饰器:@Controller()(定义控制器+路由前缀)、@Get()/@Post()/@Put()/@Delete()(请求方法)、@Param()/@Query()/@Body()(参数获取)

    • 示例:@Controller('user') 定义/user前缀路由,@Get(':id') 匹配/user/:id路径

  • Service 服务层(业务核心)

    • 核心职责:封装业务逻辑、处理数据、调用数据库或其他服务,是业务逻辑的核心载体

    • 核心装饰器:@Injectable()(标记为可注入对象,供Controller或其他Service注入使用)

    • 特点:独立于Controller,可被多个Controller复用,便于单元测试

  • Module 模块层(架构核心)

    • 核心装饰器:@Module(),包含4个核心属性:imports(导入其他模块)、controllers(注册当前模块的控制器)、providers(注册当前模块的服务)、exports(导出服务,供其他模块使用)

    • 作用:模块化拆分业务,实现代码隔离,大型项目可按业务领域拆分(如UserModule、AuthModule)

    • 根模块:AppModule,是整个项目的入口模块,负责全局配置

  • Repository 数据层(数据操作)

    • 基于TypeORM实现,对应数据库表的CRUD操作,封装数据访问逻辑

    • 核心:实体(Entity)定义数据表结构,Repository对象执行数据库操作

  • AOP相关层(统一处理)

    • Guard 守卫:负责权限鉴权、登录验证

    • Interceptor 拦截器:负责请求预处理、响应包装、日志记录等

    • Filter 异常过滤器:负责全局异常捕获和统一格式化

    • Pipe 管道:负责参数校验、数据转换

2. 依赖注入 DI(NestJS 核心 · 进阶要点)

  • 定义:由Nest容器统一管理对象的创建、依赖关系的注入,开发者无需手动new对象,只需声明依赖即可

  • 核心装饰器:@Injectable()(标记类为可注入的Provider)

  • 注入方式(要点对照):

    • 构造函数注入(推荐):通过构造函数参数声明依赖,Nest自动注入,支持类型推断

    • 属性注入:通过@Inject()装饰器注入属性,不推荐(不利于单元测试)

  • 核心作用:解耦代码(降低模块间依赖)、易于单元测试(可Mock依赖)、便于功能替换

  • 关键要点:

    • 跨模块注入:需在依赖模块的exports中导出服务,当前模块imports导入依赖模块

    • 循环依赖问题:当两个模块/服务互相依赖时,使用forwardRef()包裹注入,解决循环引用

    • Provider类型:类提供者(默认)、值提供者、工厂提供者、异步工厂提供者

3. AOP面向切面编程(高级重点)

  • 核心思想:在不修改原有代码的前提下,对代码进行增强(如统一鉴权、日志、异常处理),实现关注点分离

  • NestJS四大切面(执行顺序重点):

    1. 管道 Pipe:最先执行,负责参数校验、数据转换(如校验请求体格式、转换参数类型)

    2. 守卫 Guard:参数校验通过后执行,负责权限鉴权、登录验证,返回boolean决定是否放行

    3. 拦截器 Interceptor:分为请求阶段(进入Controller前)和响应阶段(Controller执行后),负责请求预处理、响应包装等

    4. 异常过滤器 ExceptionFilter:最后执行,捕获整个请求流程中的所有异常,统一格式化返回

  • 完整执行流程(建议熟悉): 客户端请求 → 全局中间件 → 全局管道 → 路由管道 → 全局守卫 → 路由守卫 → 全局拦截器(请求阶段) → 控制器拦截器(请求阶段) → Controller → Service → 控制器拦截器(响应阶段) → 全局拦截器(响应阶段) → 异常过滤器(如有异常) → 返回客户端

三、NestJS 路由 & 请求参数(实战基础)

1. 路由装饰器

  • @Controller('prefix'):定义控制器的路由前缀,如@Controller('user'),所有该控制器的路由都以/user开头

  • 请求方法装饰器:@Get(path)、@Post(path)、@Put(path)、@Delete(path),path为子路由

  • 辅助装饰器:

    • @HttpCode(code):修改响应状态码(如@HttpCode(204))

    • @Redirect(url, statusCode):实现重定向

    • @Header(key, value):设置响应头

2. 参数获取装饰器(实战重点)

  • @Request():获取原始Express/Koa的req对象(不推荐,尽量使用专用装饰器)

  • @Response():获取原始res对象(慎用,会失去Nest的响应处理机制)

  • @Param(paramName?):获取路径参数,如@Param('id')获取/user/:id中的id

  • @Query(paramName?):获取URL查询参数,如@Query('page')获取?page=1中的page

  • @Body(paramName?):获取请求体数据(POST/PUT请求),如@Body()获取整个请求体,@Body('name')获取请求体中的name字段

  • @Headers(headerName?):获取请求头,如@Headers('Authorization')获取授权头

  • @Ip():获取客户端IP地址

3. 全局路由 & 版本控制

  • 全局路由前缀:main.ts中通过app.setGlobalPrefix('api')设置,所有路由都会加上/api前缀(如/api/user)

  • 路由版本控制(实战常用):

    • 方式1:装饰器方式,@Controller({ path: 'user', version: '1' })

    • 方式2:全局配置,设置版本前缀(如/api/v1/user)

四、Pipe 管道(参数校验)

1. 管道核心作用

  • 参数校验:验证请求参数(路径、查询、请求体)的格式、类型、范围,不符合则抛出异常

  • 数据转换:将请求参数转换为所需类型(如字符串转数字)

  • 数据清洗:过滤无效参数、移除多余字段

2. 内置管道(常用)

  • ValidationPipe:参数校验核心管道,配合class-validator使用(企业标配)

  • ParseIntPipe:将参数转换为number类型,转换失败抛出异常

  • ParseUUIDPipe:验证参数是否为UUID格式

  • DefaultValuePipe:为参数设置默认值

3. class-validator + class-transformer(企业实战标配)

  • DTO数据传输对象(Data Transfer Object):

    • 定义:用class(而非interface)定义请求参数的结构和校验规则,interface仅用于类型提示,无法用于运行时校验

    • 作用:规范请求参数格式、实现运行时校验、避免非法参数传入

  • 常用校验装饰器(必记):

    • IsString():验证参数为字符串

    • IsNumber():验证参数为数字

    • IsEmail():验证参数为邮箱格式

    • MinLength(n):验证字符串最小长度

    • MaxLength(n):验证字符串最大长度

    • IsOptional():参数可选

    • IsEnum(enum):验证参数为指定枚举值

  • 全局启用校验(实战必写):main.ts中 app.useGlobalPipes(new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true, transform: true }))

    • whitelist: true:自动移除请求体中未定义的字段

    • forbidNonWhitelisted: true:存在未定义字段时抛出异常

    • transform: true:自动将参数转换为DTO中定义的类型

4. 自定义管道

  • 实现 PipeTransform 接口,重写transform方法(接收参数和上下文)

  • 作用:处理特殊的参数校验或转换需求(如密码加密、日期格式化)

五、Guard 守卫(权限鉴权)

1. 守卫核心作用

  • 鉴权:验证用户是否登录、是否拥有操作权限(如管理员权限)

  • 接口拦截:根据业务规则拦截请求(如黑名单拦截)

  • 核心:实现 CanActivate 接口,重写canActivate方法,返回boolean(true放行,false拦截)

2. 常用鉴权方案(实战重点)

  • JWT守卫(最常用):

    • 流程:提取请求头中的Authorization: Bearer token → 验证token签名 → 解析用户信息 → 注入请求上下文

    • 实现:自定义JWTGuard,结合PassportModule使用

  • 角色权限守卫(RoleGuard):

    • 通过@SetMetadata('roles', ['admin'])设置接口所需角色

    • 守卫中获取元数据,对比用户角色,判断是否放行

3. 关键要点

  • 执行时机:路由匹配后、进入Controller之前

  • 核心限制:不能修改请求和响应数据,仅负责“放行/拦截”

  • 作用范围:全局守卫、控制器守卫、方法守卫(优先级:方法 > 控制器 > 全局)

六、Interceptor 拦截器(AOP 核心)

1. 拦截器核心作用

  • 请求预处理:修改请求参数、添加请求头、记录请求日志

  • 响应后处理:统一包装响应格式、修改响应数据、压缩响应

  • 其他:接口超时处理、接口缓存、异常转换、日志记录

  • 核心:实现 NestInterceptor 接口,重写intercept方法(使用Observable处理异步流)

2. 实战核心场景(必写)

  • 统一响应格式(企业必做): 所有接口统一返回 { code: number, data: any, msg: string },Controller直接返回data,拦截器统一包装

  • 接口缓存:对常见查询接口进行缓存,减少数据库压力

  • 日志记录:记录请求的URL、参数、响应时间、响应结果

3. 关键要点

  • 执行顺序:全局拦截器 → 控制器拦截器 → 方法拦截器(请求阶段);响应阶段相反

  • 核心优势:可修改请求和响应数据,支持异步处理,与Guard的核心区别的是“可修改数据”

七、ExceptionFilter 异常过滤器(全局错误处理)

1. 核心作用

  • 统一捕获:捕获整个请求流程中的所有异常(管道、守卫、Controller、Service中的异常)

  • 统一格式化:将所有异常转换为统一的错误响应格式(如 { code: 500, msg: '服务器错误', error: '' })

  • 日志记录:记录错误信息,便于排查问题

  • 核心:实现 ExceptionFilter 接口,重写catch方法

2. 内置异常(常用)

  • HttpException:基础HTTP异常,可自定义状态码和错误信息

  • BadRequestException:400错误(参数错误)

  • UnauthorizedException:401错误(未登录)

  • ForbiddenException:403错误(无权限)

  • NotFoundException:404错误(资源不存在)

  • InternalServerErrorException:500错误(服务器内部错误)

3. 全局异常过滤器(实战必写)

  • 方式1:main.ts中 app.useGlobalFilters(new GlobalExceptionFilter())

  • 方式2:通过模块 providers 注册,支持依赖注入

  • 核心:区分业务异常和系统异常,分别处理,避免暴露敏感错误信息

八、TypeORM 数据库(NestJS实战核心·重点)

1. TypeORM 基础认知

  • ORM(对象关系映射)框架,TS原生支持,可操作MySQL、PostgreSQL、SQLite等多种数据库

  • 核心思想:将数据库表映射为TS类(实体Entity),通过Repository对象执行CRUD操作,无需编写原生SQL

  • NestJS集成:通过TypeModule.forRoot()配置数据库连接

2. 实体Entity定义(实战必写)

  • @Entity('table_name'):标记类为实体,对应数据库表(table_name可省略,默认用类名小写)

  • 常用字段装饰器:

    • @PrimaryGeneratedColumn():自增主键(int类型)

    • @PrimaryColumn():自定义主键(如UUID)

    • @Column():普通字段,可指定类型、长度、是否可为空等

    • @CreateDateColumn():自动记录创建时间

    • @UpdateDateColumn():自动记录更新时间

    • @Column({ type: 'varchar', length: 50, nullable: false }):完整配置示例

3. Repository模式(数据操作核心)

  • Repository:对应实体的数据库操作对象,由Nest自动注入

  • 注入方式:constructor(private userRepo: Repository<User>) {}

  • 常用方法(必记):

    • find():查询所有数据

    • findOneBy({ id: 1 }):根据条件查询单条数据

    • save():新增/修改数据(根据是否有主键判断)

    • update(id, data):根据主键更新数据

    • delete(id):根据主键删除数据

    • createQueryBuilder():构建复杂SQL查询(联表查询、分页等)

4. 关联查询(高级重点)

  • 一对一(@OneToOne):如User和UserProfile(一个用户对应一个个人资料)

  • 一对多(@OneToMany):如User和Article(一个用户对应多篇文章)

  • 多对一(@ManyToOne):如Article和User(多篇文章对应一个用户)

  • 多对多(@ManyToMany):如User和Role(一个用户可拥有多个角色,一个角色可对应多个用户)

5. 配置 & 迁移(实战重点)

  • 配置文件:data-source.ts(TypeORM 0.3+)或ormconfig.ts,配置数据库类型、主机、端口、用户名、密码、数据库名等

  • 数据库迁移(重点):

    • 作用:版本控制数据库结构,避免手动修改表结构导致的问题

    • 命令:typeorm migration:create(创建迁移文件)、typeorm migration:run(执行迁移)、typeorm migration:revert(回滚迁移)

    • 关键坑点:生产环境禁止设置synchronize: true(会自动同步实体到数据库,可能导致删表毁库)

九、NestJS 中间件 Middleware

  • 核心区别(要点对照):中间件是Express/Koa原生功能,执行时机最早(在管道、守卫之前),只能访问req和res对象,无法访问Nest的上下文

  • 作用:日志记录、跨域处理(cors)、解析cookie(cookie-parser)、解析JSON(express.json())

  • Nest中使用:

    • 实现 NestMiddleware 接口,重写use方法

    • 在Module中通过configure方法配置,或在main.ts中使用app.use()全局注册

十、NestJS 跨域、Cookie、JWT认证(前端对接重点)

1. CORS跨域配置(实战必写)

  • main.ts中启用:app.enableCors({}),支持配置参数:

    • origin:允许访问的域名(例如 ['http://localhost:3000'],生产环境指定具体域名,禁止用 *

    • methods:允许的请求方法(如['GET', 'POST', 'PUT', 'DELETE'])

    • credentials:允许携带Cookie(需设为true,配合前端withCredentials: true)

  • 集成cookie-parser:解析请求头中的Cookie,挂载到req.cookies

  • Session配置:结合express-session,存储会话信息(推荐用Redis存储,支持分布式)

  • Cookie安全配置:SameSite(防止CSRF)、httpOnly(禁止前端操作Cookie)、secure(HTTPS下生效)

3. JWT完整认证流程(常见要点)

  1. 用户登录:客户端提交账号密码,Service层验证账号密码是否正确

  2. 生成Token:验证通过后,服务端生成access_token(访问令牌,有效期短)和refresh_token(刷新令牌,有效期长)

  3. 返回Token:将两个Token返回给客户端,客户端存储(access_token存内存,refresh_token存Cookie/ localStorage)

  4. 请求接口:客户端后续请求时,在请求头携带Authorization: Bearer access_token

  5. Token验证:JWT守卫拦截请求,提取Token,验证签名和有效期,解析用户信息并注入请求上下文

  6. Token过期处理:access_token过期后,客户端用refresh_token请求刷新接口,获取新的access_token;refresh_token过期则要求用户重新登录

4. JWT优缺点(要点对照)

  • 优点:无状态(无需服务器存储会话信息)、分布式友好(多服务可共享Token)、无需Redis等中间件

  • 缺点:无法主动注销(Token生成后有效期内一直有效)、payload是明文(不能存储敏感信息)、体积较大(会增加请求头开销)

十一、NestJS 微服务 & 网关

1. Nest 微服务 Microservice

  • 核心:将大型项目拆分为多个独立的微服务(如用户服务、商品服务),服务间通过TCP、Redis、MQ、GRPC等方式通信

  • 关键特性:服务发现、负载均衡、故障转移、统一配置

  • 适用场景:大型项目,需要水平扩展、服务解耦的场景

2. Nest Gateway 网关

  • 核心:微服务架构的统一入口,负责路由转发、鉴权、限流、日志、监控等

  • 作用:隐藏微服务细节,客户端只需对接网关,无需关心微服务的部署和通信

3. WebSocket 网关

  • 核心:实现客户端与服务器的双向通信,基于WebSocket协议

  • 装饰器:@WebSocketGateway(port) 标记为WebSocket网关

  • 适用场景:聊天室、实时通知、实时监控等

十二、NestJS 单元测试 & 部署

1. 单元测试 Jest(NestJS内置)

  • 核心优势:依赖注入机制使单元测试更简单,可轻松Mock Service、Repository等依赖

  • 测试对象:Controller(测试路由和参数解析)、Service(测试业务逻辑)、Guard(测试鉴权逻辑)、Pipe(测试参数校验)

  • 常用方法:jest.mock()(Mock依赖)、expect()(断言结果)

2. 项目部署流程(实战建议掌握)

  1. 编译:将TS代码编译为JS代码,生成dist目录(npm run build)

  2. 进程守护:使用PM2启动dist/main.js,实现进程守护(防止进程崩溃)

  3. 反向代理:配置Nginx,将客户端请求反向代理到Node服务(处理静态资源、HTTPS、负载均衡)

  4. 环境配置:使用.env文件区分开发(dev)、测试(test)、生产(prod)环境,通过ConfigService读取配置

  5. 数据库:执行数据库迁移(typeorm migration:run),配置数据库备份策略

3. 环境变量配置

  • 安装@nestjs/config,配置.env文件,存储数据库地址、端口、JWT密钥等敏感信息

  • 通过ConfigService注入配置,如this.configService.get('DATABASE_URL')

十三、NestJS 常见难点&坑点(进阶辨析)

  • 1. 循环依赖问题:Module之间、Service之间互相依赖,解决方案:使用forwardRef()包裹注入的模块/服务

  • 2. DI依赖注入原理:Nest容器在应用启动时,扫描所有@Injectable()标记的类,创建实例并管理依赖关系,注入到需要的地方

  • 3. 四大切面执行顺序(重点):管道 → 守卫 → 拦截器(请求阶段) → Controller → 拦截器(响应阶段) → 异常过滤器

  • 4. DTO vs Interface区别:Interface仅用于TS类型提示,无运行时校验;DTO是class,配合class-validator可实现运行时校验,可实例化

  • 5. 生产环境禁止synchronize: true:该配置会自动将实体同步到数据库,若实体删除字段,会自动删除数据库表字段,导致数据丢失

  • 6. JWT无状态如何实现退出登录:方案1:Redis维护Token黑名单;方案2:缩短access_token有效期,刷新token;方案3:前端删除存储的Token(伪退出)

  • 7. Guard和Interceptor区别:Guard仅负责放行/拦截,不能修改请求响应;Interceptor可修改请求响应,支持异步处理,执行时机在Guard之后

  • 8. 全局/模块/方法级别的拦截器、过滤器优先级:方法级 > 控制器级 > 全局级

  • 9. Express和Fastify区别:Fastify性能比Express高,支持异步路由,NestJS可通过配置切换底层框架

  • 10. TypeORM事务:多表操作需保证原子性(要么全部成功,要么全部失败),使用transaction方法或@Transaction()装饰器