NestJs快速入门
介绍nestjs
NestJs 是一个渐进的 Node.js 框架,可以在 TypeScript 和 JavaScript (ES6、ES7、ES8)之上构建高效、可伸缩的企业级服务器端应用程序。
NestJs 基于 TypeScript 编写并且结合了 OOP(面向对象编程),FP(函数式编程)和 FRP (函数式响应编程)的相关理念。在设计上的很多灵感来自于 Angular,Angular 的很多模式又来自于 Java 中的 Spring 框架,依赖注入、面向切面编程等,所以我们也可以认为: NestJs 是 Node.js 版的 Spring 框架。
NestJs 框架底层 HTTP 平台默认是基于 Express 实现的,所以无需担心第三方库的缺失。 NestJs 旨在成为一个与平台无关的框架。 通过平台,可以创建可重用的逻辑部件,开发人员可以利用这些部件来跨越多种不同类型的应用程序。 从技术上讲,NestJs 可以在创建适配器后使用任何 Node HTTP 框架。 有两个支持开箱即用的 HTTP 平台:express 和 fastify。 您可以选择最适合您需求的产品。
NestJs 的核心思想:就是提供了一个层与层直接的耦合度极小,抽象化极高的一个架构体系。
NestJs脚手架及常用命令
- 安装:npm i -g @nestjs/cli 或者 cnpm i -g @nestjs/cli 或者 yarn global add @nestjs/cli
- 创建:nest new project-name
- 相关命令:
- nest new 名称 创建项目
- nest -h/--help 帮助
- nest g co 名称 创建控制器
- nest g s 名称 创建服务
- nest g mi 名称 创建中间件
- nest g pi 名称 创建管道
- nest g mo 名称 创建模块
- nest g gu 名称 创建守卫
- 凡是以脚手架创建的模块,控制器等等都会自动添加到对应配置位置,不需要手动配置
概述
控制器
- NestJs 中的控制器层负责处理传入的请求, 并返回对客户端的响应。
- NestJs 能够创建路由映射,Controller将请求绑定到相应的控制器。
- NestJs 也提供了其他 HTTP 请求方法的装饰器 @Put() 、@Delete()、@Patch()、 @Options()、 @Head()和 @All()
- 在 NestJs 中获取 Get 传值或者 Post 提交的数据的话我们可以使用 Nestjs 中的装饰器@Query()和@Body()来获取
提供者
NestJs 中的提供者负责逻辑处理和与数据层打交道。他们通过 constructor注入依赖关系提供者是以@Injectable() 装饰器注解的类。
模块
NestJs 中的模块是具有 @Module() 装饰器的类。 @Module() 装饰器提供了元数据,Nest 用它来组织应用程序结构。
因为上面根模块 App.modules 已经引入过该模块,所以其他模块就可以直接使用user模块的Service
中间件
中间件就是匹配路由之前或者匹配路由完成做的一系列的操作。中间件中如果想往下匹配的话,使用 next()
中间件的任务:
- 执行任何代码
- 对请求和响应对象进行更改
- 结束请求-响应周期
- 调用堆栈中的下一个中间件函数
- 如果当前的中间件函数没有结束请求-响应周期, 它必须调用 next() 将控制传递给下一个中间 件函数。否则, 请求将被挂起
异常过滤器
内置的异常层负责处理整个应用程序中的所有抛出的异常。当捕获到未处理的异常时,最终用户将收到友好的响应
管道
NestJs 中的管道可以将输入数据转换为所需的输出。此外,它也可以处理验证, 当数据不正确时可能会抛出异常。具有 @Injectable() 装饰器的类。管道需要实现 PipeTransform 接口。
守卫
守卫是一个使用 @Injectable() 装饰器的类。守卫应该实现 CanActivate 接口
守卫有一个单独的责任。它们确定请求是否应该由路由处理程序处理。到目前为止,访问限制逻辑大多在中间件内。这样很好,因为诸如 token 验证或将 request 对象附加属性与特定路由没有强关联。但中间件是非常笨的。它不知道调用 next() 函数后会执行哪个处理程序。另一方面,守卫可以访问 ExecutionContext 对象,所以我们确切知道将要执行什么
简单的说就是在 Nextjs 中如果我们想做权限判断的话可以在守卫中完成,也可以在中间件中完成,但是一般通过守卫最好
拦截器
拦截器具有一系列有用的功能,这些功能受面向切面编程(AOP)技术的启发。它们可以:
- 在函数执行之前/之后绑定额外的逻辑
- 转换从函数返回的结果
- 转换从函数抛出的异常
- 扩展基本函数行为
- 根据所选条件完全重写函数 (例如, 缓存目的)
NestJs的执行链路
客户端请求-->中间件-->守卫 -->拦截器之前 -->管道--> 控制器处理并响应-->拦截器之后-->过滤器
- 接收客户端发起请求
- 中间件去做请求处理,比如helmet,csrf,rate limiting,compression等等常用的处理请求的中间件
- 守卫就验证该用户的身份,如果没有权限或者没有登录,就直接抛出异常,最适合做权限管理
- 拦截器根据文档的解释,拦截器之前不能修改请求信息。只能获取请求信息
- 管道做请求的数据验证和转化,如果验证失败抛出异常
- 这里处理响应请求的业务,俗称controller,处理请求和服务桥梁,直接响应服务处理结果
- 拦截器之后只能修改响应body数据
- 最后走过滤器:如果前面任何位置发生抛出异常操作,都会直接走它
总结
NestJs很多提供的内部功能,看似功能重复,但是实际上有明确的职责划分,按照约定来,能使结构清晰,代码更好维护
- 模块是按业务逻辑划分基本单元,包含控制器和服务。控制器是处理请求和响应数据的部件,服务处理实际业务逻辑的部件
- 中间件是路由处理Handler前的数据处理层,只能在模块或者全局注册,可以做日志处理中间件、用户认证中间件等处理,中间件和express的中间件一样,所以可以访问整个request、response的上下文,模块作用域可以依赖注入服务。全局注册只能是一个纯函数或者一个高阶函数
- 管道是数据流处理,在中间件后路由处理前做数据处理,可以控制器中的类、方法、方法参数、全局注册使用,只能是一个纯函数。可以做数据验证,数据转换等数据处理
- 守卫是决定请求是否可以到达对应的路由处理器,能够知道当前路由的执行上下文,可以控制器中的类、方法、全局注册使用,可以做角色守卫
- 拦截器是进入控制器之前和之后处理相关逻辑,能够知道当前路由的执行上下文,可以控制器中的类、方法、全局注册使用,可以做日志、事务处理、异常处理、响应数据格式等
- 过滤器是捕获错误信息,返回响应给客户端。可以控制器中的类、方法、全局注册使用,可以做自定义响应异常格式
- 中间件、过滤器、管道、守卫、拦截器,这是几个比较容易混淆的东西。他们有个共同点都是和控制器挂钩的 东西。他们有个共同点都是和控制器挂钩的中间抽象处理层,但是他们的职责却不一样