You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS中如何在两个不同路由下共享同一FoodModule

问题根源

NestJS模块默认是单例模式,FoodModule被导入后只会初始化一次。你在RouterModule中重复将同一个FoodModule挂载到不同父路由下时,后注册的路由配置会覆盖之前的,因此只有最后一个(/dogs/food)生效。

解决方案:拆分服务与控制器,子模块创建专属路由控制器

核心思路是将Food的业务逻辑抽为共享服务,在CatsModule和DogsModule中分别创建专属控制器,绑定各自的路由前缀,同时复用同一个FoodService。

步骤1:重构FoodModule,仅保留共享服务

修改food/food.module.ts,移除控制器并导出服务:

import { Module } from '@nestjs/common';
import { FoodService } from './food.service';

@Module({
  providers: [FoodService],
  exports: [FoodService], // 导出服务供其他模块注入
})
export class FoodModule {}

步骤2:在CatsModule中创建专属Food控制器

新建cats/cats-food.controller.ts,绑定/cats/food路由:

import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common';
import { FoodService } from '../food/food.service';

@Controller('cats/food')
export class CatsFoodController {
  constructor(private readonly foodService: FoodService) {}

  @Post()
  create(@Body() createFoodDto) {
    return this.foodService.create(createFoodDto);
  }

  @Get()
  findAll() {
    return this.foodService.findAll();
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.foodService.findOne(+id);
  }

  @Patch(':id')
  update(@Param('id') id: string, @Body() updateFoodDto) {
    return this.foodService.update(+id, updateFoodDto);
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.foodService.remove(+id);
  }
}

更新cats/cats.module.ts,导入FoodModule并添加新控制器:

import { Module } from '@nestjs/common';
import { CatsService } from './cats.service';
import { CatsController } from './cats.controller';
import { FoodModule } from '../food/food.module';
import { CatsFoodController } from './cats-food.controller';

@Module({
  imports: [FoodModule],
  controllers: [CatsController, CatsFoodController],
  providers: [CatsService],
})
export class CatsModule {}

步骤3:在DogsModule中重复相同操作

新建dogs/dogs-food.controller.ts,绑定/dogs/food路由:

import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common';
import { FoodService } from '../food/food.service';

@Controller('dogs/food')
export class DogsFoodController {
  constructor(private readonly foodService: FoodService) {}

  @Post()
  create(@Body() createFoodDto) {
    return this.foodService.create(createFoodDto);
  }

  @Get()
  findAll() {
    return this.foodService.findAll();
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.foodService.findOne(+id);
  }

  @Patch(':id')
  update(@Param('id') id: string, @Body() updateFoodDto) {
    return this.foodService.update(+id, updateFoodDto);
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.foodService.remove(+id);
  }
}

更新dogs/dogs.module.ts:

import { Module } from '@nestjs/common';
import { DogsService } from './dogs.service';
import { DogsController } from './dogs.controller';
import { FoodModule } from '../food/food.module';
import { DogsFoodController } from './dogs-food.controller';

@Module({
  imports: [FoodModule],
  controllers: [DogsController, DogsFoodController],
  providers: [DogsService],
})
export class DogsModule {}

步骤4:简化AppModule配置

移除RouterModule中关于food的配置,同时删除直接导入的FoodModule(子模块已导入):

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CatsModule } from './cats/cats.module';
import { DogsModule } from './dogs/dogs.module';

@Module({
  imports: [CatsModule, DogsModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
验证效果

启动应用后,控制台会输出以下路由映射:

  • /cats/food的所有CRUD路由
  • /dogs/food的所有CRUD路由
    两个路由将共享FoodService的业务逻辑,符合预期需求。

内容的提问来源于stack exchange,提问作者devesh-verma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 08:57:33