NestJS入門controller、DTO、providers、module。
官方API位址https://docs.nestjs.com/
Nest(或NestJS)是一個用于建構高效,可擴充的Node.js伺服器端應用程式的架構。也可以在Nest中使用express架構的擴充
安裝(官方也有推薦)
npm i -g @nestjs/cli //全局安裝腳手架
nest new project-name //使用腳手架建立nest項目
腳手架建立的項目自帶:@nestjs/core @nestjs/common rxjs reflect-metadata這些依賴
項目目錄:src下面的主要檔案
xxx.controller.ts 是一個nest的路由控制器
xxx.controller.spec.ts 是一個控制器測試檔案
xxx.service.ts 對應的服務,把控制器的一些實作過程的抽離,讓controller檔案不會太過臃腫,也減少了耦合度
xxx.module.ts 是把控制器,服務等注冊成一個應用程式的子產品檔案
main.ts 主要檔案,是程式的主入口,也是啟動整個項目的主檔案,可以和express那樣配置中間件等操作,使用核心功能NestFactory建立Nest應用程式執行個體的應用程式的條目檔案。
1.控制器 (路由控制器)
用裝飾器書寫後端路由
@Controller() // 裝飾一個類,把類注冊成路由控制器,可以傳遞字元串路由參數或者路由表達式等
例如: @Controller(‘user’) => 每次請求内部路由方法:localhost:3000/user …
Get, Post, Put, Delete, Patch等裝飾器修飾類的方法,把方法注冊成每一個路由,分别是get、post、put、delete、patch請求等
// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller('user') //(注冊路由必選裝飾器),傳入一個可選參數,可以讓類内部所有的路由加上這個參數,/user user 看習慣一個樣
export class AppController {
// constructor構造函數建立之後,會在providers中找到對應的被Injectable修飾的類,注入到這裡
constructor(private readonly appService: AppService) { } // Nest是圍繞通常稱為依賴注入的強大設計模式建構的,類型解析
@Get() // 把這個類方法注冊成一個get路由
public getHello(): string {
return 'Hello World';
}
}
// app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
controllers: [AppController], // 在此子產品中定義的控制器集,必須進行執行個體化
providers: [AppService], // 注冊服務成一個提供者,提供給controller使用
})
export class AppModule { }
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { NestExpressApplication } from '@nestjs/platform-express';
async function bootstrap() {
// const app = await NestFactory.create<NestExpressApplication>(AppModule); // 使用express
// 設定全局字首
// app.setGlobalPrefix('/api');
const app = await NestFactory.create(AppModule); // 預設使用
await app.listen(3000);
}
bootstrap();
設定全局字首 app.setGlobalPrefix(’/api’); //然後整個API請求都需要加上/api
這時候用get請求通路http://localhost:3000/user就會傳回一個字元串 'Hello World'
這時候用get請求通路http://localhost:3000/user就會傳回一個字元串 'Hello World'
Get, Post, Put, Delete, Patch等裝飾器也可以傳遞字元串參數或者一些正規表達式
//方式1 比對/
@Get()
//方式2 比對/get
@Get('get') // or @Get('/get')
//方式3 比對/get/字元串id
@Get('get/:id')
//方式4 比對/user/任意字元
@Get('user/*')
Post, Put, Delete, Patch等裝飾器也是一樣的用法,以及類裝飾器Controller也是可以這樣寫
Post, Put, Delete, Patch等裝飾器也是一樣的用法,以及類裝飾器Controller也是可以這樣寫
當getHello方法的邏輯操作過于頻繁的情況下,可以抽離出來,寫到service服務層上面,讓邏輯更加清晰,耦合度降低
//app.service.ts
import { Injectable } from '@nestjs/common';
/**
* 控制器應處理HTTP請求并将更複雜的任務委派給提供者。提供程式是純類JavaScript類,在@Injectable()類聲明之前有一個裝飾器。
* * Injectable裝飾器,控制反轉(“IoC”)容器
*/
@Injectable() // 控制反轉(“IoC”)容器
export class AppService<T = any> {
public getHello(): string {
return 'Hello World!';
}
}
服務層 使用Injectable裝飾器裝飾,讓module子產品層的providers能夠掃描到這個服務層,用于controller層的注入,使得抽離出的部分寫在service層
這時候的app.controller.ts
這時候的app.controller.ts
// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller('user') //(注冊路由必選裝飾器),傳入一個可選參數,可以讓類内部所有的路由加上這個參數,/user user 看習慣一個樣
export class AppController {
// constructor構造函數建立之後,會在providers中找到對應的被Injectable修飾的類,注入到這裡
constructor(private readonly appService: AppService) { } // Nest是圍繞通常稱為依賴注入的強大設計模式建構的,類型解析
@Get() // 把這個類方法注冊成一個get路由
public getHello(): string {
return this.appService.getHello();
}
}
這樣的結果也是一緻的.
其它:
當你需要接收前端傳遞過來的參數,擷取請求頭、擷取session、request、response、next的時候,可以使用形參裝飾器
// app.controller.ts
import { Controller, Get, Post, Body } from '@nestjs/common';
import { AppService } from './app.service';
@Controller('user') //(注冊路由必選裝飾器),傳入一個可選參數,可以讓類内部所有的路由加上這個參數,/user user 看習慣一個樣
export class AppController {
// constructor構造函數建立之後,會在providers中找到對應的被Injectable修飾的類,注入到這裡
constructor(private readonly appService: AppService) { } // Nest是圍繞通常稱為依賴注入的強大設計模式建構的,類型解析
@Get() // 把這個類方法注冊成一個get路由
public getHello(): string {
return this.appService.getHello();
}
@Post('/body')//擷取body裡面的name參數并傳回
public getBody(@Body('name') name: string): string {
return name;
}
}
@Body(‘name’) //擷取整個body對象的name屬性的值
@Body() //則表示擷取整個body對象
Param、Headers、Query、Session等用法一緻
還有一些裝飾器:
HttpCode:成功傳回的status 預設是200
Redirect:請求重定向,讓這個請求結果重定向到Redirect的那個uri
Next, Res, Req就是express的三劍客了,相信都知道的了,用這三個裝飾變量,即可獲得對應的屬性
@HttpCode(202) // 讓成功的響應從預設值200變成202
@Get('test')
public test(@Req() request: Request, @Res() response: Response, @Next() next: (url?: string) => void): string {
// next('/url');
// next();
return 'test';
}
2.DTO 資料傳輸對象(架構) 用于存放傳輸的資料,例如擷取的資料對象、傳回的資料對象
// body.dto.ts
export class CreateBodyDto {
public readonly username: string;
public readonly password: string;
}
建立一個body dto,用于接收整個body
// app.controller.ts 補充
import { CreateBodyDto } from './DTO/body.dto';
@Post('/body')
public validate(@Body() body: CreateBodyDto): CreateBodyDto {
return body;
}
當然@Body() body: any 也是可以的,但是這樣違背了ts的強類型語言的特點,同時也降低了代碼的複用性等,讓代碼的可讀性更差,使用DTO類來修飾接收或者傳回的參數的情況下,可以有更友好的提示和複用性等。
dto:主要用于資料傳輸對象,就是接收對象或者傳回的對象,都可以,使用也較為簡單
3.providers
被Injectable裝飾器修飾的類就是一個服務,服務可以0個,也可以多個,然後注冊在module的providers中,提供給controller等使用
@Module({
controllers: [AppController], // 在此子產品中定義的控制器集,必須進行執行個體化,可以多個,一個控制器數組
providers:[appService,pageService...] // 一個服務的數組
})
export class AppModule { }
可選服務
import { Injectable, Optional, Inject } from '@nestjs/common';
/**
* 控制器應處理HTTP請求并将更複雜的任務委派給提供者。提供程式是純類JavaScript類,在@Injectable()類聲明之前有一個裝飾器。
* * Injectable裝飾器,控制反轉(“IoC”)容器
*/
@Injectable() // 控制反轉(“IoC”)容器
export class AppService<T = any> {
public getHello(): string {
return 'Hello World!';
}
// Inject 注入:可以基于構造函數的注入,也可以是基于屬性的注入
// Optional 可選的 加上這個注解最後,表示這個參數的注入是可以選的
@Optional()
@Inject('HTTP_OPTIONS') // Identification:辨別/token:令牌 提供一個唯一的辨別,防止重複
private readonly course: T;
}
Optional, Inject 裝飾屬性,可以告訴nest,這是可選的一個選項,同時也是可以注入的選項,這些注入是nest自動注入的,我們可以在相應的情況下調用這些。
4.module 子產品是用@Module()裝飾器注釋的類。
每個應用程式至少有一個子產品,一個根子產品。@Module()接收一個對象,參數如下:
- providers 将由Nest注入器執行個體化的提供程式,并且至少可以在此子產品中共享
- controllers 在此子產品中定義的控制器集,必須進行執行個體化
- imports 導出此子產品中所需的提供程式的導入子產品清單
- exports 其子集providers由此子產品提供,并且應該在導入此子產品的其他子產品中可用
而我們上面的例子就用到了providers、controllers兩個接收數組的屬性
當我們需要對子產品進行拆分的時候,可以使用imports接收一個子產品數組
// child.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
controllers: [AppController], // 在此子產品中定義的控制器集,必須進行執行個體化
providers: [AppService],
exports: [AppService],
})
// 實作NestModule接口,進而配置中間件
export class ChildModule implements NestModule { }
每個子產品都自動成為共享子產品。一旦建立,它可以被任何子產品重用。
我們想要共享AppService服務的執行個體給其它子產品使用,為了做到這一點,我們需要導出providers裡面的服務,提供給其他子產品使用
改造app.module.ts
import { Module } from '@nestjs/common';
// import { AppController } from './app.controller';
// import { AppService } from './app.service';
import { ChildModule } from './child.module';
@Module({
imports: [ChildModule], // 導出此子產品中所需的提供程式的導入子產品清單,就是把module子產品劃分成一個個子子產品,然後導入到這個子產品當中
// controllers: [AppController], // 在此子產品中定義的控制器集,必須進行執行個體化
// providers: [AppService], // 注冊服務成一個提供者,提供給controller使用
})
export class AppModule { }
exports 也可以用于子產品重新導出,讓此子產品給其他子產品使用,而不是直接給主子產品.
子產品類也可以注入提供者(例如,用于
配置
目的)
import { Global, Module } from '@nestjs/common';
@Global()
@Module({
//...
})
export class AppModule {
constructor(private readonly catsService: CatsService) {}
}
@Global()裝飾子產品後這個子產品就是全局子產品,全局子產品隻應注冊一次,通常由根子產品或核心子產品注冊。
動态子產品,此功能使您可以輕松建立可自定義的子產品
// database.module.ts
import { Module, DynamicModule } from '@nestjs/common';
@Module({})
export class DatabaseModule {
static forRoot(entities = [], options?): DynamicModule { // forRoot()方法可以同步或異步(即通過a Promise)傳回動态子產品。
return {
module: DatabaseModule, // 子產品就是自己這個類
providers: entities, //傳回的子產品
// exports: entities, //導出的子產品 exports的子集就是providers
};
}
}
forRoot()方法可以同步或異步(即通過a Promise)傳回動态子產品
動态子產品的使用
import { Module } from '@nestjs/common';
import { ChildModule } from './child.module';
import { DatabaseModule } from './database.module';
@Module({
imports: [DatabaseModule.forRoot([ChildModule])],
exports: [DatabaseModule],
})
export class AppModule {}
覺得不錯就收個藏什麼的,謝謝
先介紹一下nest的基本控制器使用、DTO、provider、module的使用,下節介紹中間件middleware、異常過濾器exceptionFilter、管道pipe的使用
先介紹一下nest的基本控制器使用、DTO、provider、module的使用,下節介紹中間件middleware、異常過濾器exceptionFilter、管道pipe的使用
其它部落格:
其它部落格:
routing-controllers、class-validator、typedi的使用總結(express使用類似nest控制器的裝飾器寫法等)
Type-GraphQL結合裝飾器寫法的node架構的學習筆記
等等等…