Nestjs-路由前缀(全局、模块、控制器)

2,662 阅读2分钟

Nest中文官方文档

全局路由前缀

在为我们的应用设计路由接口的时候,如果需要有一个固定的前缀,比如需要说明一个指定的版本:

https://myHost.com.cn/app/private/v1

可以使用Nest提供的全局路由前缀方式设置,这里是官方地址

const app = await NestFactory.create(AppModule);
app.setGlobalPrefix('app/private/v1');
控制器路由前缀

当然, 也可以在控制器Controller级别设置路由前缀:

// user.controller.ts
import { Controller, Get } from '@nestjs/common';

@Controller('users')
export class UsersController {
  @Get(:id)
  getUser(): string {
    return 'This action returns user by id';
  }
}

请求方式就是这样:

https://myHost.com.cn/app/private/v1/users/123
Module路由

对于Module级路由前缀的设置,是通过RouterModule类来设置的,这里是文档地址,示例如下:

@Module({
  imports: [
    RouterModule.register([
      {
        path: 'users', // 定义前缀
        module: UsersModule // 应用在哪个moudule上
      }
    ]),
    UsersModule
  ],
  controllers: [],
  providers: [],
})
export class AppModule {
  constructor() { }
}

通过官方文档介绍,通过这种方式还可以定义层次结构,每个Module可以有子Module,子Module将继承父Module的前缀。官方示例如下:

RouterModule.register([
  {
    path: 'admin',
    module: AdminModule,
    children: [
      {
        path: 'dashboard',
        module: DashboardModule,
      },
      {
        path: 'metrics',
        module: MetricsModule,
      },
    ],
  },
]);

这样,请求方式就是:

***/admin/dashboard/***
***/admin/metrics/***

这样看来,当我们面对复杂业务场景、复杂项目,需要对路由进行设计和规划的时候,Nest提供的这种框架层面的设计,就保证了极大的自由度,去控制和组织好项目的代码结构。

一个小问题

RouterModule.register方法接收的参数是routerTree[]routerTree的定义如下:

export interface RouteTree {
    path: string;
    module?: Type<any>;
    children?: Routes | Type<any>[];
}

module是可选的。我尝试用下面的方式设置:

@Module({
  imports: [
    RouterModule.register([
      {
        path: 'users', // 定义前缀
      }
    ]),
    UsersModule
  ],
  controllers: [],
  providers: [],
})
export class AppModule {
  constructor() { }
}

发现没有效果,既不是全局定义,也不是所在Module级别的定义,目前还搞不懂,如果有大佬知道,希望不吝赐教!。。。

另一个设置Module前缀的方法(不推荐)

好奇心驱使下,查看了下Nest源码的创建Router部分:

首先查看了route-path-factory.js这个文件,是用来创建路由路径的工厂函数,在create方法里传入的metadata参数里,定义了modulePath、ctrlPath、methodPath、globalPrefix属性,这些应该就是用来拼接路由的。

nest-route-2.jpg

继续向上查找,找到了routes-resolver.js文件,在这里找到了create方法的调用位置和metadata是如何组装的:

nest-route-3.jpg

并进一步找到了modulePath的取值位置:

nest-route-4.jpg

看到这里,modulePath是通过Reflect取的MODULE_PATHMODULE_PATH的定义是这样的:

export declare const MODULE_PATH = "__module_path__";

所以,要定义Moudle级路由前缀modulePath,可以通过SetMetadata设置MODULE_PATH。示例如下:

import { Module } from '@nestjs/common';
import {  SetMetadata } from '@nestjs/common';
import { MODULE_PATH } from '@nestjs/common/constants';

@SetMetadata(MODULE_PATH, 'manager')
@Module({
  imports: [...],
  providers: [...],
  controllers: [...],
  exports: [...],
})
export class ManagerModule { }

总结

以上内容官网均有涉及,浅浅记录,不值一提。如有错误,欢迎指正!!!

Nest中文官网Nest英文官网内容不同步,英文官网更全更新一些,RouterModule的使用说明也是在英文官网发现的, 在中文官网没有找到。