一天学会nextjs
前端工程师极速入门 NestJS 后端 — 实战学习笔记(含全套习题答案)
前言(前端视角)
作为前端开发者学习 NestJS,无需深究后端底层原理、操作系统、服务器内核等复杂知识,核心目标是打通前后端开发链路,独立开发可用、规范、符合企业标准的后端接口。
前端入门 NestJS 只需要掌握核心 6 大能力:
- 基础 CRUD 接口编写
- 精准接收前端各类请求参数
- 统一接口响应格式,适配前端 Axios 拦截器
- 生产级跨域配置
- 第三方数据库/工具全局挂载
- JWT 登录鉴权、接口权限控制
本文基于实战踩坑经验总结,贴合前端思维,0 后端基础可直接上手,学完可独立开发完整前后端项目。
一、NestJS 核心架构(前端必懂核心)
1. 核心分层架构(企业固定规范)
NestJS 最核心的执行链路:Controller(控制器)→ Service(业务层)
- Controller 控制器:只负责「对接前端」,接收请求、解析参数、调用业务服务,不写任何业务逻辑
- Service 业务服务:只负责「处理逻辑」,数据校验、数据库操作、业务计算、数据处理,不直接对接前端请求
前端口诀(必背):控制器只传话,服务层干实事,职责分离不混乱。
2. 依赖注入(前端最易理解的核心特性)
依赖注入是 NestJS 的核心设计,彻底告别手动实例化类,解决前端开发者初学后端最大的困惑。
核心代码示例:
typescript |
通俗白话解析:
- 无需手动new AuthService()实例化
- 只需给 Service 类添加@Injectable()装饰器
- Nest 框架自动全局创建单例实例,全局唯一
- 控制器直接通过this.authService.xxx()调用方法
前端类比理解:等同于全局挂载的公共工具类,项目启动自动初始化,任意页面/模块直接调用。
二、控制器全套语法(前端必会 100%)
1. @Controller 路由前缀配置
统一模块路由前缀,简化接口路径,是企业开发标准化写法。
typescript |
企业规范:99% 的业务模块必须配置统一路由前缀,方便接口管理、版本迭代。
2. 四大核心请求方式(对应前端所有请求场景)
完全对齐前端 Axios 请求方法,一一对应,无学习成本:
- @Get():查询数据(列表、详情、分页数据)
- @Post():新增数据、登录、提交表单
- @Patch():局部更新数据(只修改部分字段)
- @Delete():删除数据(单条/批量删除)
3. 前端参数接收(重中之重,对接前端核心)
前端所有传参方式,仅对应 4 种后端装饰器,全覆盖无遗漏:
① 路径参数 @Param(动态路由 /:id)
适用场景:获取单条详情、删除单条数据、修改单条数据
typescript |
核心关键点:
- URL 路径参数默认都是字符串类型,后端需要数字类型必须转换
- ParseIntPipe 两大核心作用:自动字符串转数字、非法参数直接返回 400 错误,拦截无效请求
② 查询参数 @Query(URL 拼接 ?key=value)
适用场景:分页查询、条件筛选、关键词搜索、多参数筛选
typescript |
③ 请求体参数 @Body(Post/Patch 表单参数)
适用场景:新增数据、批量修改、复杂表单提交
typescript |
④ 完整请求对象 @Request()
适用场景:获取请求头、登录用户信息、Cookie 等原生请求数据
typescript |
三、管道 Pipe 核心知识点(参数校验神器)
ParseIntPipe(前端开发高频使用)
是入门阶段最常用、必须掌握的内置管道,专门处理数字类型参数。
核心两大作用:
- 类型转换:自动将 URL 字符串参数转为 Number 数字类型
- 参数校验:参数为空、字母、特殊符号等非法格式,直接返回 400 客户端错误,不会进入业务逻辑
强制规范:所有 ID、页码、偏移量等数字参数,必须添加 ParseIntPipe 校验。
四、全局拦截器(统一返回格式,适配前端)
1. 核心作用
统一项目所有接口的响应结构,解决后端接口返回格式不统一、前端适配繁琐的问题,完美对接前端 Axios 全局拦截器。
2. 标准统一响应结构
json |
3. 前端核心收益
前端无需逐个适配接口返回格式,只需配置一次 Axios 拦截器,统一处理成功、失败状态,大幅减少重复代码。
五、跨域 CORS 原理(生产级配置)
项目采用白名单动态跨域方案,是企业生产环境标准写法,区别于开发环境的全局放行。
核心特性
- 精准放行:仅允许配置的前端域名、IP 跨域请求
- 测试兼容:Postman、Apifox 等无 Origin 的测试工具可直接放行
- 安全拦截:陌生域名、非法请求直接拦截,杜绝跨域安全风险
优劣对比
app.enableCors():全局放行所有跨域请求,仅适合本地开发,线上生产环境禁止使用,存在安全隐患。
六、全局模块 Global + 自定义依赖注入
以 ClickHouse 数据库模块为例,讲解第三方工具、数据库的全局挂载方案,适配所有全局工具。
1. @Global() 全局模块装饰器
被该装饰器标记的模块为全局模块,全项目所有模块无需手动导入,可直接注入使用。
适用场景:数据库连接、日志工具、缓存、全局常量、公共工具方法。
2. 自定义注入令牌
第三方库、原生实例无法通过类注入,必须使用「字符串令牌 + @Inject」实现注入。
typescript |
七、登录鉴权守卫(AuthGuard)
守卫是 NestJS 权限控制核心,先校验、后执行接口逻辑,高效实现接口权限管控。
1. 两种核心守卫(全覆盖登录/权限场景)
- AuthGuard('local'):本地账号密码守卫,仅用于登录接口,校验用户名、密码是否正确
- AuthGuard('jwt'):令牌校验守卫,用于所有需要登录权限的接口,校验 Token 有效性
2. 守卫执行优先级
守卫执行顺序:请求进来 → 守卫校验 → 接口逻辑执行
Token 缺失、过期、错误、无效,直接返回 401 未授权错误,不会进入业务代码。
3. req.user 核心知识点
req.user 不是 Node 原生对象,是 JWT 守卫解析 Token 后,自动挂载到请求对象上的用户信息,可直接在接口中获取当前登录用户。
八、前端开发者专属必背总结
- Controller 只负责接参、转发请求,绝对不写业务逻辑
- Service 统一处理业务逻辑、数据操作、数据库查询
- 所有数字类型参数(ID、页码)必须搭配 ParseIntPipe 校验
- 全局工具/数据库采用 @Global 全局模块 + 自定义令牌注入
- 统一接口响应格式使用全局拦截器
- 接口权限、登录校验使用守卫 AuthGuard
- 生产环境必须使用白名单跨域,禁止全局跨域放行
九、企业级实战练习题(前端转后端专用)+ 完整标准答案
所有练习题均来自真实项目开发场景,完成后可直接写入简历,适配中小企业全栈开发需求。
练习1:规范商品模块接口(基础夯实)
需求:
- 给商品模块所有 @Param 路径参数(id)添加 ParseIntPipe 类型校验
- 依托全局响应拦截器,统一所有 CRUD 接口返回格式
- 配置接口权限:新增/修改/删除接口需 JWT 鉴权,查询接口公开访问
标准答案
typescript |
练习2:生产级跨域配置改造
需求:
- 改造现有跨域配置,支持前端携带 Token、Cookie 跨域请求
- 配置多环境白名单(本地开发、测试环境、线上生产环境域名)
标准答案(main.ts)
typescript |
练习3:封装全局日志模块(高频面试考点)
需求:模仿 ClickHouse 全局模块写法,封装项目全局日志工具
- 新建 LoggerModule 并设置为 @Global 全局模块
- 封装日志方法(打印请求地址、请求方式、请求参数、请求时间)
- 在商品 CRUD 接口中调用日志方法,记录每一次前端请求
标准答案
src/logger/logger.service.ts
typescript |
src/logger/logger.module.ts(全局模块)
typescript |
在商品控制器使用
typescript |
练习4:精细化接口鉴权(真实项目权限逻辑)
需求:实现差异化权限控制,贴合后台管理系统真实场景
- 登录接口、注册接口:无需 Token,公开访问
- 商品列表、商品详情查询接口:无需 Token,公开访问
- 商品新增、编辑、删除接口:必须携带有效 JWT Token,未登录直接拦截
标准答案(最终权限规则)
直接复用【练习1】代码即可实现:
- 登录、注册、商品查询:无@UseGuards,公开访问
- 新增/修改/删除:添加@UseGuards(AuthGuard('jwt'))强制鉴权
练习5:全局统一异常处理(项目必备优化)
需求:配合现有响应拦截器,完善项目异常处理机制
- 创建全局异常过滤器,捕获项目所有未知错误、业务错误
- 统一错误返回格式:code=500、message=错误描述、data=null
- 区分参数错误、权限错误、服务器错误,返回对应提示
标准答案:全局异常过滤器 src/filter/http-exception.filter.ts
typescript |
main.ts 全局注册
typescript |
练习6:前端适配型分页接口(Table 组件专用)
需求:改造商品列表接口,适配 Ant Design/Element Plus 表格组件分页需求
- 接收前端传入的 page(当前页码)、pageSize(每页条数)参数
- 后端实现分页查询逻辑,统计数据总数
- 固定返回结构:{ page, pageSize, total, list }
标准答案
分页 DTO:query-product.dto.ts
typescript |
Service 分页逻辑
typescript |
