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四大切面(执行顺序重点):
管道 Pipe:最先执行,负责参数校验、数据转换(如校验请求体格式、转换参数类型)
守卫 Guard:参数校验通过后执行,负责权限鉴权、登录验证,返回boolean决定是否放行
拦截器 Interceptor:分为请求阶段(进入Controller前)和响应阶段(Controller执行后),负责请求预处理、响应包装等
异常过滤器 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)
2. Cookie & Session
集成cookie-parser:解析请求头中的Cookie,挂载到req.cookies
Session配置:结合express-session,存储会话信息(推荐用Redis存储,支持分布式)
Cookie安全配置:SameSite(防止CSRF)、httpOnly(禁止前端操作Cookie)、secure(HTTPS下生效)
3. JWT完整认证流程(常见要点)
用户登录:客户端提交账号密码,Service层验证账号密码是否正确
生成Token:验证通过后,服务端生成access_token(访问令牌,有效期短)和refresh_token(刷新令牌,有效期长)
返回Token:将两个Token返回给客户端,客户端存储(access_token存内存,refresh_token存Cookie/ localStorage)
请求接口:客户端后续请求时,在请求头携带Authorization: Bearer access_token
Token验证:JWT守卫拦截请求,提取Token,验证签名和有效期,解析用户信息并注入请求上下文
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. 项目部署流程(实战建议掌握)
编译:将TS代码编译为JS代码,生成dist目录(npm run build)
进程守护:使用PM2启动dist/main.js,实现进程守护(防止进程崩溃)
反向代理:配置Nginx,将客户端请求反向代理到Node服务(处理静态资源、HTTPS、负载均衡)
环境配置:使用.env文件区分开发(dev)、测试(test)、生产(prod)环境,通过ConfigService读取配置
数据库:执行数据库迁移(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()装饰器
