Skip to content

3. Nest 基础概念扫盲

Nest 是对标 Java 的 Spring 框架的后端框架,它有很多概念。

对于新手来说,上来就接触这些概念可能会有点懵。

这节我们集中来过一下(这节不用实践,理解概念就好):

我们通过不同的 url 来访问后端接口:

/user/create

/user/list

/book/create

/book/list

不同的 url 是不同的路由。

这些路由在 Controller 里声明:

比如这里就是声明了一个 /user/create 的 post 接口,声明了一个 /user/list 的 get 接口。

在 class 上和它方法的方法上加上 @Controller、@Get、@Post 的装饰器就可以了。

controller 的方法叫做 handler,是处理路由的。

post 的请求体,get 的请求参数,都可以通过装饰来取:

通过 @Param 取 url 中的参数,比如 /user/111 里的 111

通过 @Query 来取 url 中的 query 参数,比如 /user/xx?id=222 里的 222

通过 @Body 取 /book/create 的请求体内容:

请求体一般会传递 json,比如 { username: 'xxx', password: 'xxx' }

我们会通过 dto (data transfer object)来接收。

传递到 handler 的就已经是 dto 对象了。

也就是说 controller 是处理路由和解析请求参数的

请求参数解析出来了,下一步就是做业务逻辑的处理了,这些东西不写在 controller 里,而是放在 service 里。

service 里做业务逻辑的具体实现,比如操作数据库等

同理,/book/list、/book/create 接口是在另一个 BookController 里:

它的业务逻辑实现也是在 BookService 里。

很明显,UserController 和 UserService 是一块的,BookController 和 BookService 是一块的。

所以,Nest 有了模块的划分,每个模块里都包含 controller 和 service:

通过 @Module 声明模块,它包含 controllers 和 providers。

为啥不是 services 而是 providers 呢?

因为 Nest 实现了一套依赖注入机制,叫做 IoC(Inverse of Control 反转控制)。

简单说就是你只需要声明依赖了啥就行,不需要手动去 new 依赖,Nest 的 IoC 容器会自动给你创建并注入依赖。

比如这个 UserController 依赖了 JwtService,那只需要通过 @Inject 声明依赖,然后就可以在方法里用了:

运行的时候会自动查找这个 JwtServcie 的实例来注入。

在 @Module 里的 providers 数组里,就是声明要往 IoC 容器里提供的对象,所以这里叫做 providers。

provider 有很多种写法:

默认的 XxxService 只是一种简化的写法。

还可以直接 useValue 创建,通过 useFactory 创建等。

刚才提到了 IoC 会自动从容器中查找实例来注入,注入的方式有两种:

属性注入和构造器注入。

这种写在构造器里的依赖,就是构造器注入。

@Inject 写在属性上的依赖,就是属性注入。

效果是一样的,只是注入的时机不同。

每个模块都会包含 controller、service、module、dto、entities 这些东西:

controller 是处理路由,解析请求参数的。

service 是处理业务逻辑的,比如操作数据库。

dto 是封装请求参数的。

entities 是封装对应数据库表的实体的。

nest 应用跑起来后,会从 AppModule 开始解析,初始化 IoC 容器,加载所有的 service 到容器里,然后解析 controller 里的路由,接下来就可以接收请求了。

其实这种架构叫做 MVC 模式,也就是 model、view、controller。

controller 接收请求参数,交给 model 处理(model 就是处理 service 业务逻辑,处理 repository 数据库访问),然后返回 view,也就是响应。

应用中会有很多 controller、service,那如果是跨多个 controller 的逻辑呢?

这种在 Nest 提供了 AOP (Aspect Oriented Programming 面向切面编程)的机制

具体来说,有 Middleware、Guard、Interceptor、Pipe、Exception Filter 这五种。

它们都是在目标 controller 的 handler 前后,额外加一段逻辑的。

比如你可以通过 interceptor 实现请求到响应的时间的记录:

这种逻辑适合放在 controller 里么?

不适合,这种通用逻辑应该通过 interceptor 等方式抽离出来,然后需要用的时候在 controller 上声明一下:

这些就是 Nest 的核心概念了。

此外,创建 Nest 项目自然也是有 cli 工具的。

比如创建新项目:

创建项目里的某个新模块:

都可以通过 @nestjs/cli 来做。

所以我们后面的学习顺序是先学会 cli 的使用,然后学习 Nest 的核心概念,之后学下涉及到的数据库、orm 框架等,最后来做项目实战。

总结

这节我们讲了很多 Nest 里的概念。

比如 controller、handler、service、dto、module、entity、ioc、aop、nest cli 等。

controller:控制器,用于处理路由,解析请求参数

handler:控制器里处理路由的方法

service:实现业务逻辑的地方,比如操作数据库等

dto:data transfer object,数据传输对象,用于封装请求体里数据的对象

module:模块,包含 controller、service 等,比如用户模块、书籍模块

entity:对应数据库表的实体

ioc:Inverse of Controller,反转控制或者叫依赖注入,只要声明依赖,运行时 Nest 会自动注入依赖的实例

aop:Aspect Oriented Programming 面向切面编程,在多个请求响应流程中可以复用的逻辑,比如日志记录等,具体包含 middleware、interceotor、guard、exception filter、pipe

nest cli:创建项目、创建模块、创建 controller、创建 service 等都可以用这个 cli 工具来做

现在只要能大概理解概念就行,后面我们会深入学习这些。