跳到主要内容

5.1-nestjs

Create by fall on 20 Sep 2023 Recently revised in 06 Aug 2024

nestjs

可以简单地将 nestjs 理解为 node 化的 java,直接沿用了很多 java 中的概念到 nodejs 上

安装:

npm i @nestjs/cli -g
# 查看 nest 版本
nest -v

项目目录

文件名称作用
app.controller.ts带有单个路由的基本控制器。
app.controller.spec.ts针对控制器的单元测试。
app.module.tsT应用程序的根模块(root module)。
app.service.ts具有单一方法的基本服务(service)。 method.
main.ts应用程序的入口文件,它使用核心函数 NestFactory 来创建 Nest 应用程序的实例。

逐个查看

// main.ts
import { NestFactory } from '@nestjs/core'; // 引入工厂函数
import { AppModule } from './app.module'; // 引入应用总入口
async function bootstrap() {
const app = await NestFactory.create(AppModule); // 工厂函数创建应用
// app.setGlobalPrefix('/api') // 可以为全局请求添加前缀
await app.listen(6000);// 应用监听 6000 端口
}
bootstrap()
// app.module.ts
import { Module } from '@nestjs/common';
@Module({
imports: [], // 向装饰器中提供 module(模块)
controllers: [], // 向装饰器中提供控制器
providers: [], // 向装饰器中提供控服务,或者是依赖注入(inject),或者是其它服务
})
export class AppModule {} // 导出一个装饰器修饰过的 AppModule

创建文件命令

nest 建议去使用命令行添加文件,因此我们会通过命令行添加 module、controller

创建一个新的应用

# 创建新的 service
nest g app new-app # 会创建一个新的应用
# 创建新的 module,module 可以简写为 mo
nest g module gonest # 其中 g 是 generate 的简写
# 创建新的 controller,可以简写为 co
nest g controller gonest
# 创建新的 service,可以简写为 s
nest g service gonest
# 创建新的 middleware,可以简写为 mi
nest g middleware gonest
# 创建全部内容,可以选择生成不同风格的内容
nest g resource [name]

创建服务

一般 module 作为核心,引入 service(服务)和 controller(控制器)

import { Module } from '@nestjs/common';
import { GonestController } from './gonest.controller';
import { GonestService } from './gonest.service';

@Module({
controllers: [GonestController], // 该模块对应的 controller
providers: [GonestService],
})
export class GonestModule {} // 导出的 module 可以被当做模块进行引用

controller 控制层,控制用户请求执行那些方法

import { Controller, Get } from '@nestjs/common';
import { GonestService } from './gonest.service';
@Controller('gonest')
export class GonestController {
constructor(private readonly gonestService:GonestService){}
// this.gonestService = new GonestService
@Get('module')
faraway():Record<'name',any> {
return this.gonestService.faraway()
}
}

service 服务层,写一些解耦的服务,提供 controll 进行调用

import { Injectable } from '@nestjs/common';
@Injectable()
export class GonestService {
faraway() {
return { name: 'peace' }
}
}

请求参数

请求参数

import { Controller, Get, Post,Request , Req , Body, Query } from '@nestjs/common';
import { GonestService } from './gonest.service';
@Controller('gonest')
export class GonestController {
constructor(private readonly gonestService: GonestService) { }
@Get('module')
faraway(@Request() req): string {
console.log(req);
return "without service"
}
@Get('modulePeach')// @Request 装饰器可以简写为 Req
faraway(@Req() req): string {
console.log(req);
return "without service"
}
@Post('dismiss') // Request 对象中的 body 属性可以直接通过 Body 装饰器获取到
getDBData(@Body() body):string {
console.log(body);
return this.gonestService.getLocalData('6479746')
}
@Post('remiss') // Request 对象中的 query 属性可以直接通过 Query 装饰器获取到
getDBData(@Query() query):string {
console.log(query);
return this.gonestService.getLocalData('6479746')
}
// 其它也能直接获取的装饰器有 IP, Headers, Res
}

有效请求荷载

一般会创建一个 dto(Data Transfer Object),比起使用 TS 的 interface 和 type,更倾向于使用 class,因为编译成 js 后,class 关键字会被保留

create-cat.dto.ts

export class CreateCatDto {
name: string;
age: number;
breed: string;
}
// 这些内容会作为白名单,任何没有在白名单中的属性都会被忽略

code.controller.ts

@Post()
async create(@Body() createCatDto: CreateCatDto) {
return 'This action adds a new cat';
}

动态路由

路由中可以添加多个符号来表示不同的含义

import { Controller, Get, Post,Req, Param } from '@nestjs/common';
import { GonestService } from './gonest.service';
@Controller('gonest')
export class GonestController {
constructor(private readonly gonestService: GonestService) { }
@Get('module/:userName') // 通过 :userName 的方式获取到当前的 userName,可以写多个动态路由
faraway(@Param() param): string { // 装饰器 Param 等价于 req.params,通过 params 获取动态路由的参数
console.log(param.userName);
return "without service"
}
}

子路径路由

@Controller({host:'admin.example.com'})
export class AdminController {
@Get()
index(): string {
return 'Admin page';
}
}

通配符

通配符只在 express 模式中支持

*'ab*cd' 路由将会匹配 abcdab_cdabecd

状态码、头文件

@Controller('code')
export class CodeController {
@Post()
@HttpCode(204) // 更新 Http Code
@Header('Cache-Control', 'none') // 指定响应头
create() {
return 'This action adds a new cat';
}

@Get()
findAll(@Res({ passthrough: true }) res: Response) {
res.status(HttpStatus.OK);
return []
}
}

重定向

如果想要动态重定向的内容,需要返回一个值

// @Redirect('https://nestjs.com', 301) // 重定向,两个参数都可选,第二个参数默认为 302
@Get('docs')
@Redirect('https://docs.nestjs.com', 302)
getDocs(@Query('version') version) {
if (version && version === '5') {
return { url: 'https://docs.nestjs.com/v5/' };
}
}

配置文件

{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "apps/nest-playground/src",
"compilerOptions": {
"deleteOutDir": true,
"webpack": true,
"tsConfigPath": "apps/nest-playground/tsconfig.app.json"
},
"monorepo": true,
"root": "apps/nest-playground",
"projects": {
"nest-playground": {
"type": "application",
"root": "apps/nest-playground",
"entryFile": "main",
"sourceRoot": "apps/nest-playground/src",
"compilerOptions": {
"tsConfigPath": "apps/nest-playground/tsconfig.app.json"
}
},
"second": {
"type": "application",
"root": "apps/second",
"entryFile": "main",
"sourceRoot": "apps/second/src",
"compilerOptions": {
"tsConfigPath": "apps/second/tsconfig.app.json"
}
}
}
}

参考文章

作者链接