Nest入门教程(三:模块)

109 阅读3分钟

Nest 模块

基本概念

模块是带有@Module()装饰器的类。@Module()装饰器提供元数据,Nest使用这些元数据来组织应用程序的结构。

image.png

@Module()装饰器接受一个单一的对象作为参数,其属性描述了模块:

providers将由 Nest 注入器实例化并且至少可以在该模块中共享的提供程序享。
controllers此模块中定义的必须实例化的控制器集
imports导出此模块所需的提供程序的导入模块列表
exports这个模块提供的providers子集应该在引入此模块的其他模块中可用。您可以使用提供者本身,也可以只使用其标记(provide值)。

当我们使用nest g res User、nest g res Order 创建一个CURD模板的时候 nestjs 会通过imports自动帮我们引入模块

// app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserModule } from './user/user.module';
import { OrderModule } from './order/order.module';

@Module({
  imports: [UserModule, OrderModule], // 导入模块集合
  controllers: [AppController], // 注入控制器集合
  providers: [AppService], // 注入服务集合
})
export class AppModule {}

共享模块

user.module.ts里通过exports导出UserService服务

// user.module.ts
import { Module } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';

@Module({
  controllers: [UserController],
  providers: [UserService],
  exports: [UserService],// 导出UserService服务
})
export class UserModule {}
// user.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class UserService {
  getUserName() {
    return 'Aiolimp';
  }
}

此时在Order模块任何地方都可以共享UserService的服务了

order.service.ts引入UserService,可以通过Inject或者构造函数注入UserService服务

// order.service.ts
import { Inject,Injectable } from '@nestjs/common';
import { UserService } from 'src/user/user.service';

@Injectable()
export class OrderService {
  @Inject(UserService) // 依赖注入UserService服务
  private readonly userService: UserService;

  // constructor(  private readonly userService: UserService){}  //构造函数注入UserService服务
  getOrderDesc():string {
    let name = this.userService.getUserName()
    return `Order获取到的用户名为:${name}`;
  }
}
// order.controller.ts
import { Controller, Get } from '@nestjs/common';
import { OrderService } from './order.service';
@Controller('order')
export class OrderController {
  constructor(private readonly orderService: OrderService) {}
  @Get()
  getOrderDesc() {
    return this.orderService.getOrderDesc();
  }
}

最后在浏览器访问http://localhost:3000/order

image.png

全局模块

使用**@Global**装饰器可以声明全局模块,此时无需在每个模块通过import重复声明

user.module.ts

import { Module,Global } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';

@Global() // 全局模块,所有模块都可以使用UserService服务
@Module({
  controllers: [UserController],
  providers: [UserService],
  exports: [UserService],// 导出UserService服务
})
export class UserModule {}

order.module.ts

import { Module } from '@nestjs/common';
import { OrderService } from './order.service';
import { OrderController } from './order.controller';
import { UserModule } from '../user/user.module';

@Module({
  // UserModule注册成了全局模块,这里无需再导入
  // imports: [UserModule],
  controllers: [OrderController],
  providers: [OrderService],
})
export class OrderModule {}

动态模块

动态模块主要就是为了给模块传递参数 可以给该模块添加一个静态方法 用来接受参数

使用forRoot在Nest中注册根模块,例如配置根模块的全局服务或者中间等

// config.module.ts
import { Module,DynamicModule } from '@nestjs/common';


interface Options {
    path: string
}
@Module({})
export class ConfigModule {
    static forRoot(options: Options): DynamicModule {
        // 在此方法中根据需要创建模块
        return {
            module: ConfigModule,
            providers: [
                {
                    provide: 'CONFIG_OPTIONS', // 自定义服务提供者的名称
                    useValue: { baseApi: "/api" + options.path } // 提供的服务提供者的值,这里是一个数组,包含了要注入的实体类
                }
            ], // 这里可以添加一些服务提供者,用于配置模块的功能
            exports: [
                {
                    provide: "Config",
                    useValue: { baseApi: "/api" + options.path }
                }
            ]
        };
    }
}

app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserModule } from './user/user.module';
import { OrderModule } from './order/order.module';
import { ConfigModule } from './config/config.module';

@Module({
  imports: [UserModule, OrderModule, ConfigModule.forRoot({path:'aiolimp'})], // 导入模块集合
  controllers: [AppController], // 注入控制器集合
  providers: [AppService], // 注入服务集合
})
export class AppModule {}