NodeJS-NestJS基础
本文介绍 NestJS 框架相关的基础知识:NestJS框架介绍、环境搭建、MVC框架解析、模块Module、控制器Controller、服务Service、中间件Middleware、守卫Guard、管道Pipe等
供自己以后查漏补缺,也欢迎同道朋友交流学习。
引言
最近跟着满神学完了 NestJS 框架,也想记录下自己的学习过程。所以本文主要介绍 NestJS 框架相关的基础知识。
首先说下为什么学 NestJS 的原因,国内主流的一些 Node 框架还是 Express 或者 Koa,如果是企业级一般用 Egg。我选择 NestJS 是因为看到很多 AI 公司及外企的招聘 JD 都在用 NestJS,想着学一学对未来找工作更好。而且 NestJS 框架的底层默认是 Express,也支持 Fastify,学习成本也不高。
后来在 B 站找了学习视频和课程,接触到了 NestJS,发现它面向对象编程语法风格我非常喜欢,完全支持 TypeScript,中间件、依赖注入、模块化开发。
如果完全不了解 NodeJs,那下面的介绍会比较难上手,建议阅读下 NodeJS-基础学习。
NestJS 框架介绍
NestJS 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的框架。它利用 TypeScript 来开发强类型、可扩展的应用程序。NestJS 深受 Angular 框架的启发,因此它的架构、模块化和依赖注入系统与 Angular 有许多相似之处。以下是 NestJS 的一些核心特性和概念:
-
依赖注入(DI):使用了一个强大的依赖注入系统,这是控制反转(
IoC)容器的一个实现。依赖注入允许你将服务(例如数据库连接、工具库等)注入到你的控制器、守卫、拦截器和服务中。 -
控制器:控制器处理
HTTP请求和响应。它们通常用来定义路由和处理逻辑。 -
服务:服务是应用程序的
业务逻辑层,通常用于封装和重用逻辑,可以被控制器或其他服务调用。 -
守卫(Guards):守卫是特殊的类,可以用来预处理请求,例如
身份验证和授权。 -
拦截器(Interceptors):拦截器用于拦截处理流程,可以在调用控制器之前或之后执行代码,例如
日志记录或错误处理。 -
装饰器:广泛使用
JS的装饰器,它被用于类和方法上,提供了一种强大的方式来添加额外信息或行为。 -
中间件:支持
Express、Fastify等 HTTP 平台的中间件,允许你在应用程序中使用现有的中间件。 -
插件和钩子:提供了
生命周期钩子,允许你在应用程序的不同阶段执行代码。 -
微服务支持:支持构建
微服务架构,提供了与消息传递系统(如MQTT或WebSockets)集成的工具。 -
CQRS 和事件源:支持命令查询责任分离(
CQRS)和事件源模式,这对于构建复杂的业务逻辑和数据一致性非常有用。 -
开箱即用:内置了许多
开箱即用的解决方案,如数据库访问层、文件上传处理、缓存等。
NestJS 的设计理念是提供一个完整的解决方案,让开发者可以专注于构建业务逻辑,而不是花时间在底层架构上。
环境搭建
Node 和 Npm 环境安装
对于 NodeJs 和 Npm 的安装,我不多做介绍,可以参考以下链接:
也可以看我之前写的NodeJS-基础学习。
安装 NestJS CLI 工具
使用 CLI 工具(@nestjs/cli)快速创建新项目。
## 安装全局 NestJS CLI 工具
npm i -g @nestjs/cli
## 安装你的项目
nest new project-name
项目结构
默认生成的项目结构如下:
.
├── README.md // 项目说明
├── nest-cli.json // nest 命令文件,用于构建项目。
├── package-lock.json
├── package.json // 项目依赖包
├── src
│ ├── app.controller.spec.ts // 针对控制器的单元测试。
│ ├── app.controller.ts // 带有单个路由的基本控制器。
│ ├── app.module.ts // 应用程序的根模块(root module)。
│ ├── app.service.ts // 具有单一方法的基本服务(service)。
│ └── main.ts // 应用程序的入口文件,它使用核心函数 NestFactory 来创建 Nest 应用程序的实例。
├── test // 测试文件
│ ├── app.e2e-spec.ts
│ └── jest-e2e.json
├── tsconfig.build.json // tsconfig 文件,用于构建项目。
└── tsconfig.json
项目运行
下面命令将使用 HTTP 服务器启动应用程序,以侦听 src/main.ts 文件中所定义的端口。应用程序运行后,打开浏览器并访问 http://localhost:3000/ 地址,将看到类似 Hello World! 的信息。
npm run start
MVC经典架构解析
在 NestJS 中,app.controller.ts、app.module.ts 和 app.service.ts是三个基础且关键的文件,它们分别代表了控制器(Controller)、模块(Module)和服务(Service)的概念。这些文件共同协作,构成了NestJS应用的基础结构。这也是经典的MVC架构,下面我们逐一解析他们的作用。
app.controller.ts
控制器是处理传入请求和返回响应的部分。它通常包含了一组路由处理器(路由装饰器如@Get(), @Post(), @Put(), @Delete()等),这些处理器将特定的请求映射到处理函数上。
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
// 定义为一个控制器
@Controller()
export class AppController {
// 构造函数:注入 appService
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
// get 请求/返回 appService 的 getHello 方法
return this.appService.getHello();
}
}
AppController 类通过 @Controller() 装饰器定义为一个控制器,并且它依赖于 AppService 服务(通过构造函数注入)。@Get() 装饰器将 getHello 方法映射为 GET 请求的处理器,该方法调用了 AppService 的 getHello 方法来获取响应字符串。
app.module.ts
模块是 NestJS 中用于封装和组织相关控制器、服务、提供者( providers,如服务)和导入( imports,即其他模块)的容器。
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
// 通过@Module()装饰器定义为一个模块
@Module({
imports: [], // 其他模块
controllers: [AppController], // 控制器
providers: [AppService], // 提供者,如服务
})
export class AppModule {}
AppModule 类通过 @Module() 装饰器定义为一个模块。它指定了当前模块包含的控制器( controllers 数组中的AppController)和提供者( providers 数组中的 AppService)。由于这是一个根模块,所以 imports 数组是空的。
app.service.ts
服务是 NestJS 中用于封装业务逻辑的部分。它们可以被注入到控制器或其他服务中,以便在多个地方重用逻辑。
import { Injectable } from '@nestjs/common';
// 定义为一个可注入的服务
@Injectable()
export class AppService {
// 一般,定义数据库增删改查的方法
getHello(): string {
return 'Hello World!';
}
}
AppService 类通过 @Injectable() 装饰器定义为一个可注入的服务。它提供了一个 getHello 方法,该方法返回一个简单的字符串“ Hello World! ”。这个服务可以在控制器中被注入并调用,以返回响应给客户端。
基本概念
模块(Modules)
通过上面的 app.module.ts,我们可以知道 Modules 是用于封装和组织相关imports、controllers、providers的容器。这个文件就是相当于前端的某个页面模块容器。
每个模块都可以定义以下部分:
- controllers:处理传入请求并返回响应的组件。
- providers:封装业务逻辑和数据的组件,通常是服务。
- imports:当前模块需要依赖的其他模块列表。
- exports:当前模块希望导出以便其他模块使用的提供者(服务、组件等)列表。
Modules示例:
假设我们需要做一个用户管理的功能,我们可以创建一个名为 UserModule 的特性模块。
// User.module.ts
import { Module } from '@nestjs/common';
import { UserController } from './User.controller';
import { UserService } from './User.service';
@Module({
controllers: [UserController],
providers: [UserService],
exports: [UserService], // 可以不写,如果其他模块需要 UserService,则导出它
})
export class UserModule {}
在 AppModule 中可以导入 UserModule,在整个应用程序中被访问和使用。
控制器(Controllers)
控制器的作用是如何定义路由和处理请求。控制器负责将请求路由到相应的处理函数,并可能调用服务(Services)来执行实际的业务逻辑。
控制器的基本概念:
- 路由:控制器通过装饰器(如
@Get(),@Post(),@Put(),@Delete()等)将特定的HTTP请求方法映射到处理函数上。这些装饰器定义了请求的URL路径、请求方法以及任何请求参数。 - 动作:控制器中的处理函数被称为
动作。当请求与路由匹配时,相应的动作将被调用,并可以执行诸如验证请求、调用服务、返回响应等操作。 - 响应:动作可以返回一个
值、一个对象、一个Promise、一个Observable或是一个流(Stream),NestJS会自动将其序列化为JSON(对于对象、Promise和Observable)并发送回客户端。
import { Controller, Get, Post, Body, Patch, Param, Delete, Query } from '@nestjs/common';
import { UserService } from './user.service';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
@Controller('user')
export class UserController {
// 依赖注入
constructor(private readonly userService: UserService) {}
@Post()
create(@Body() createUserDto: CreateUserDto) {
// 调用服务来创建用户
return this.userService.create(createUserDto);
}
@Get()
findAll(@Query() query: { name: string; page: number; pageSize: number }) {
return this.userService.findAll(query);
}
// 其他动作...
}
此外,NestJS 支持 Promise 和 Observable,你可以在控制器的动作中执行异步操作,如数据库查询或 HTTP 请求。NestJS会自动等待 Promise 解析或 Observable 完成,并将结果返回给客户端。
服务(Services)
服务(Services)是封装了特定业务逻辑和数据的组件。它们通常用于处理应用程序中需要执行的任务,如数据访问、验证、转换等。服务通常不直接处理 HTTP 请求,而是由控制器(Controllers)调用以完成特定的业务操作。
可以使用@Injectable()装饰器定义一个类来创建服务:
import { Injectable } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { InjectRepository } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
import { Tags } from './entities/tags.entity';
import { Like, Repository } from 'typeorm';
@Injectable()
export class UserService {
// 注入 userRepository 用户数据库
constructor(
@InjectRepository(User) private readonly userRepository: Repository<User>,
) {}
// 创建用户
create(createUserDto: CreateUserDto) {
const data = new User();
data.name = createUserDto.name;
data.desc = createUserDto.desc;
return this.userRepository.save(data);
}
// 查询所有
async findAll(query: { name: string; page: number; pageSize: number }) {
const data = await this.userRepository.find({
where: {
name: Like(`%${query.name}%`),
},
order: {
id: 'DESC',
},
skip: (query.page - 1) * query.pageSize,
take: query.pageSize,
});
const total = await this.userRepository.count({
where: {
name: Like(`%${query.name}%`),
},
});
return {
data,
total,
};
}
// ...其他方法
}
服务通常负责以下职责:
- 数据访问:服务可以封装与数据库、文件系统或其他
数据源交互的代码。 - 业务逻辑:服务可以包含执行特定业务规则和操作的代码。
- 转换和验证:服务可以对输入数据进行验证,并将内部数据转换为适合外部使用的格式。
- 依赖管理:服务可以管理对其他服务的依赖,并将它们封装在单个接口中,以简化组件之间的交互。
依赖注入(DI)
依赖注入(Dependency Injection,简称 DI)是一种软件设计模式,它允许一个类(或对象)的依赖项在创建时或运行时被外部传入,而不是在类内部自行创建。
依赖注入的几种方式:
- 构造函数注入:通过类的
构造函数传入依赖项。 - Setter方法注入:通过类的
setter方法传入依赖项。 - 接口注入:这种方式较少使用,主要通过接口来定义依赖项,并在实现类中注入这些依赖项。
装饰器(Decorators)
在 NestJS 大量使用的装饰器,如 @Controller, @Get, @Post 等,常见的装饰器类型包括:
- 类装饰器:用于类级别,可以修改类的行为或添加元数据。
- 方法装饰器:用于方法级别,可以修改方法的行为或添加元数据。
- 属性装饰器:用于类属性级别,可以修改属性的行为或添加元数据。
- 参数装饰器:用于方法参数级别,可以访问或修改方法参数的信息。
NestJS 中的核心装饰器
- @Module():用于定义模块。
- @Injectable():用于标记服务类,使其能够由依赖注入系统管理和注入。
- @Controller():用于定义路由的基类,可以指定路由前缀。
- @Get(), @Post(), @Put(), @Delete(), ...:这些装饰器用于定义路由处理器(
Route Handlers),指定处理HTTP请求的方法(如GET、POST等)和路径。 - @Inject()、InjectRepository():用于在构造函数中注入依赖项。虽然
@Injectable()已经为服务类启用了依赖注入,但@Inject()允许你更具体地控制注入过程,特别是在处理非类依赖项时。 - @UseGuards():用于在路由处理器或整个控制器上应用守卫(
Guards)。守卫用于实现认证、授权等安全机制。
自定义装饰器
NestJS 也支持自定义装饰器,允许你根据需要定义自己的装饰器逻辑。自定义装饰器通常用于添加自定义元数据或修改类的行为。
const Log = (target: Object, key: string | symbol, descriptor: TypedPropertyDescriptor<any>) => {
const originalMethod = descriptor.value;
descriptor.value = function(...args: any[]): any {
console.log(`Calling ${key.toString()} with args`, args);
const result = originalMethod.apply(this, args);
console.log(`Called ${key.toString()}, result is ${result}`);
return result;
};
return descriptor;
};
@Log
methodToLog() {
// 方法体
}
在 NestJS 中,装饰器是实现模块化、依赖注入和面向切面编程等关键概念的重要工具。它们极大地提高了代码的可读性、可维护性和可扩展性。
进阶特性
中间件(Middleware)
中间件主要用于全局请求处理,可以用于日志记录、错误处理、身份验证等功能。
在 NestJS 中,中间件分为两种类型:
-
全局中间件:可以在整个应用程序范围内生效。
-
局部中间件:仅在特定的路由或控制器中生效。
创建和使用中间件:
首先,我们需要创建一个中间件类。中间件类需要实现 NestMiddleware 接口,并且必须有一个 use 方法来处理 HTTP 请求和响应。
// 创建中间件
import { NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log(`Request received at ${req.url}`);
next(); // 调用 next() 来传递控制权给下一个中间件或路由处理器
}
}
要将中间件应用于整个应用程序,需要在主模块(通常是 AppModule)中注册中间件。
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { LoggerMiddleware } from './middlewares/logger.middleware';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes('*'); // 应用于所有路由
}
}
如果只想在特定的路由或控制器中使用中间件,可以在路由定义时指定。
import { Controller, Get, UseMiddleware } from '@nestjs/common';
import { AppService } from './app.service';
import { LoggerMiddleware } from './middlewares/logger.middleware';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
@UseMiddleware(LoggerMiddleware) // 应用于特定的路由
getHello(): string {
return this.appService.getHello();
}
}
NestJS 还提供了一些装饰器来更方便地应用中间件:
- @UseInterceptors(): 用于应用拦截器。
- @UseGuards(): 用于应用守卫。
- @UsePipes(): 用于应用管道。
虽然这些装饰器主要用于其他目的,但在某些情况下也可以与中间件一起使用来增强功能。
管道(Pipes)
管道一般用于请求数据的转换、验证和预处理。
创建管道:
要创建一个管道,需要定义一个类,并实现 PipeTransform 接口。接口有两个方法需要实现:transform 和 parse。transform 方法用于对数据进行转换和处理,而 parse 方法用于反向操作。
下面是一个简单的管道示例,用于验证和转换 userId 参数:
// ./pipes/parse-user-id.pipe
import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } from '@nestjs/common';
@Injectable()
export class ParseUserIdPipe implements PipeTransform<string, number> {
transform(value: string, metadata: ArgumentMetadata): number {
const val = parseInt(value, 10);
if (isNaN(val)) {
throw new BadRequestException('Validation failed');
}
return val;
}
}
PipeTransform<string, number>指定了输入类型为string,输出类型为number。transform方法将字符串转换为数字,并检查转换后的值是否为NaN(非数字)。
使用管道:
管道可以通过装饰器应用到控制器的方法参数上,或者在全局范围内应用。
import { Controller, Get, Param, UsePipes } from '@nestjs/common';
import { ParseUserIdPipe } from './pipes/parse-user-id.pipe';
@Controller('users')
export class UserController {
// 使用 @UsePipes 装饰器来应用管道
@Get(':id')
@UsePipes(ParseUserIdPipe)
getUser(@Param('id') id: number) {
// id 已经被转换为数字类型
console.log(id);
return `User with ID: ${id}`;
}
}
还可以在全局范围内应用管道,这样就不需要在每个控制器方法中单独定义。
import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe());
await app.listen(3000);
}
bootstrap();
NestJS 提供了一些内置的管道,可以开箱即用:
- ValidationPipe:可以确保传入的数据符合一定的验证规则,并且可以将数据转换成期望的格式。
- ParseIntPipe:将数据转换为整数。
- ParseFloatPipe:将数据转换为浮点数。
- ParseBoolPipe:将数据转换为布尔值。
- ParseArrayPipe:将数据转换为数组。
- ParseEnumPipe:将数据转换为枚举。
- ParseUUIDPipe:将数据转换为UUID。
- DefaultValuePipe:用于在传入的参数为空或未定义时提供一个默认值。
守卫(Guards)
守卫(Guards)是一种特殊的机制,用于保护路由和控制器方法,确保只有在满足特定条件时才允许执行这些方法。
守卫主要用于以下几个方面:
-
身份验证:确保用户已登录或拥有执行某些操作所需的权限。 -
授权:确保用户具有访问资源的权限。 -
条件路由:根据某些条件决定是否应该执行某个路由处理程序。 -
错误处理:在执行路由处理程序之前捕获错误。
创建守卫:
要创建一个守卫,需要定义一个类,并实现 CanActivate 接口。
// guards/auth.guard
@@filename(auth.guard)
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable()
export class AuthGuard implements CanActivate {
// 这个接口定义了一个 `canActivate` 方法,该方法返回一个布尔值或一个返回布尔值的 `Promise`,表示是否允许请求继续。
canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> {
// 获取请求对象
const request = context.switchToHttp().getRequest();
// 检查用户是否已登录
return request.isAuthenticated();
}
}
使用守卫:
守卫可以通过装饰器应用到控制器或特定方法上
import { Controller, Get, UseGuards } from '@nestjs/common';
import { AuthGuard } from './guards/auth.guard';
@Controller('users')
@UseGuards(AuthGuard) // 应用于整个控制器
export class UsersController {
@Get()
findAll() {
return 'List of users';
}
@Get(':id')
@UseGuards(AuthGuard) // 应用于特定方法
findOne() {
return 'Details of user';
}
}
NestJS 提供了几种内置的 Guard:
- AuthGuard: 用于
身份验证。它检查请求是否包含有效的认证凭据,并在验证失败时抛出异常。 - RolesGuard: 用于基于
角色的访问控制。它确保只有具有特定角色的用户才能访问特定的路由。 - PermissionGuard: 用于基于
权限的访问控制。它确保用户具有执行特定操作的权限。 - ThrottlerGuard: 用于
速率限制。它限制用户在给定时间内可以发起的请求数量。 - WsGuard: 用于
WebSocket连接的守卫。它允许你在WebSocket连接建立之前执行一些逻辑。
拦截器(Interceptors)
拦截器(Interceptors)的作用是修改请求或响应。它们非常适合用于日志记录、性能监控、数据转换、错误处理、缓存处理等场景。
创建拦截器:
要创建一个拦截器,您需要定义一个类,并实现 Interceptor 接口。这个接口定义了一个 intercept 方法,该方法接收 ExecutionContext 和 CallHandler 作为参数。
// interceptors/logging.interceptor
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
console.log('Before...');
const now = Date.now();
// 调用 next() 来执行后续的处理
return next.handle().pipe(
tap(() => console.log(`After... ${Date.now() - now}ms`)),
);
}
}
使用拦截器:
拦截器可以通过装饰器应用到控制器或特定的方法上。
import { Controller, Get, UseInterceptors } from '@nestjs/common';
import { LoggingInterceptor } from './interceptors/logging.interceptor';
@Controller('cats')
@UseInterceptors(LoggingInterceptor) // 应用于整个控制器
export class CatsController {
@Get(':id')
@UseInterceptors(LoggingInterceptor) // 应用于特定方法
findOne() {
return 'Details of cat';
}
}
还可以在全局范围内应用拦截器,这样就不需要在每个控制器方法中单独定义。
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { PerformanceInterceptor } from './interceptors/performance.interceptor';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalInterceptors(new PerformanceInterceptor());
await app.listen(3000);
}
bootstrap();
NestJS 提供了一些内置的拦截器:
- ClassSerializerInterceptor: 用于序列化和反序列化对象,确保响应对象只包含预期的属性。
- TransformInterceptor:用于转换传入的数据,可以用于自定义数据转换逻辑。
- SerializeInterceptor:用于序列化响应数据,可以用于确保响应数据符合一定的格式。
- DeserializeInterceptor:用于反序列化请求数据,可以用于确保请求数据符合一定的格式。
异常过滤器(Exception Filters)
异常过滤器(Exception Filters)是一种用于处理未捕获的异常的机制。它们可以在应用程序抛出异常时介入,并提供自定义的错误处理逻辑。可以优雅地处理错误,统一错误响应格式,并执行额外的日志记录或其他操作。
创建异常过滤器:
要创建一个异常过滤器,需要定义一个类,并实现 ExceptionFilter 接口。这个接口定义了一个 catch 方法,该方法接收异常实例、上下文和调用处理器作为参数。
import { ExceptionFilter, Catch, ArgumentsHost, HttpException, HttpStatus } from '@nestjs/common';
import { Request, Response } from 'express';
@Catch() // 标记为全局异常过滤器
export class AllExceptionsFilter implements ExceptionFilter {
// 方法用于处理异常,并返回一个标准的 JSON 格式的错误响应。
catch(exception: unknown, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
const status =
exception instanceof HttpException
? exception.getStatus()
: HttpStatus.INTERNAL_SERVER_ERROR;
response.status(status).json({
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url,
message: exception instanceof HttpException ? exception.message : 'Internal server error',
});
}
}
异常过滤器可以通过装饰器应用到控制器或特定的方法上,也可以全局应用。
import { Controller, Get, UseFilters } from '@nestjs/common';
import { AllExceptionsFilter } from './filters/all-exceptions.filter';
@Controller('cats')
@UseFilters(AllExceptionsFilter) // 应用于整个控制器
export class CatsController {
@Get()
findAll() {
// 抛出异常
throw new Error('An error occurred');
}
}
全局应用异常过滤器
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { AllExceptionsFilter } from './filters/all-exceptions.filter';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// 全局应用异常过滤器
app.useGlobalFilters(new AllExceptionsFilter());
await app.listen(3000);
}
bootstrap();
CLI快捷命令
NestJS 提供了许多实用的 CLI(命令行接口)命令来简化项目的设置、管理和开发过程。以下是一些常用的快捷命令:
| 命令 | 别名缩写 | 描述 |
|---|---|---|
nest generate resource RESOURCE-NAME | nest g res RESOURCE-NAME | 将创建一个新的资源包含CRUD及控制器、服务、模块 |
nest generate module MODULE-NAME | nest g mo MODULE-NAME | 将创建一个新的模块(目录)以及相关的 module.ts 文件 |
nest generate controller CONTROLLER-NAME | nest g co CONTROLLER-NAME | 生成控制器,可以使用 --no-spec 标志来避免生成测试文件。这个命令会创建一个新的控制器文件和基本的路由处理方法。 |
nest generate service SERVICE-NAME | nest g s SERVICE-NAME | 生成一个新的服务类,服务通常用于封装应用逻辑。 |
nest generate guard GUARD-NAME | nest g gu GUARD-NAME | 创建用于定义应用层的安全规则的守卫。 |
nest generate interceptor INTERCEPTOR-NAME | nest g in INTERCEPTOR-NAME | 拦截器可以修改方法执行的行为,如响应、请求处理前后执行特定的逻辑。 |
nest generate filter FILTER-NAME | nest g f FILTER-NAME | 过滤器允许你处理异常或请求,以及发送自定义的响应给客户端。 |
nest generate pipe PIPE-NAME | nest g pi PIPE-NAME | 管道是处理数据的另一种方式,可以自动转换输入到路由处理器或从路由处理器转换输出。 |
实战案例
后续写一个案例