NestJS路由基础 #

路由概述 #

NestJS使用装饰器来定义路由,路由将HTTP请求映射到控制器的处理方法。路由系统是NestJS的核心功能之一。

路由定义 #

控制器路由前缀 #

使用@Controller()装饰器定义路由前缀:

typescript
@Controller('users')
export class UsersController {
  // 所有方法的路由都以 /users 开头
}

路由方法装饰器 #

typescript
import { Controller, Get, Post, Put, Patch, Delete, Options, Head, All } from '@nestjs/common';

@Controller('users')
export class UsersController {
  @Get()           // GET /users
  findAll() {}

  @Post()          // POST /users
  create() {}

  @Put()           // PUT /users
  replace() {}

  @Patch()         // PATCH /users
  update() {}

  @Delete()        // DELETE /users
  remove() {}

  @Options()       // OPTIONS /users
  getOptions() {}

  @Head()          // HEAD /users
  getHeaders() {}

  @All()           // 所有HTTP方法
  handleAll() {}
}

路由路径 #

typescript
@Controller('users')
export class UsersController {
  @Get()                    // GET /users
  findAll() {}

  @Get('profile')           // GET /users/profile
  getProfile() {}

  @Get('admin/list')        // GET /users/admin/list
  getAdminList() {}

  @Get(':id')               // GET /users/:id
  findOne() {}
}

路由匹配规则 #

匹配顺序 #

NestJS按照定义顺序匹配路由:

typescript
@Controller('users')
export class UsersController {
  @Get('profile')           // 先匹配静态路由
  getProfile() {}

  @Get(':id')               // 后匹配动态路由
  findOne() {}
}

请求示例:

请求路径 匹配方法
GET /users/profile getProfile()
GET /users/123 findOne()

通配符路由 #

typescript
@Get('ab*cd')
getWildcard() {
  return 'Matches abcd, ab_cd, ab123cd, etc.';
}

路由参数 #

基本参数 #

typescript
@Get(':id')
findOne(@Param('id') id: string) {
  return `User ID: ${id}`;
}

多个参数 #

typescript
@Get(':userId/posts/:postId')
getUserPost(
  @Param('userId') userId: string,
  @Param('postId') postId: string,
) {
  return `User: ${userId}, Post: ${postId}`;
}

获取所有参数 #

typescript
@Get(':id')
findOne(@Param() params: { id: string }) {
  return `User ID: ${params.id}`;
}

可选参数 #

typescript
@Get(':id?')
findOne(@Param('id') id?: string) {
  if (id) {
    return `User ID: ${id}`;
  }
  return 'All users';
}

路由分组 #

版本控制 #

typescript
@Controller({
  path: 'users',
  version: '1',
})
export class UsersV1Controller {
  @Get()
  findAll() {
    return 'Users V1';
  }
}

@Controller({
  path: 'users',
  version: '2',
})
export class UsersV2Controller {
  @Get()
  findAll() {
    return 'Users V2';
  }
}

启用版本控制:

typescript
import { VersioningType } from '@nestjs/common';

const app = await NestFactory.create(AppModule);
app.enableVersioning({
  type: VersioningType.URI,
});

主机路由 #

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

动态主机 #

typescript
@Controller({ host: ':tenant.example.com' })
export class TenantController {
  @Get()
  index(@HostParam('tenant') tenant: string) {
    return `Tenant: ${tenant}`;
  }
}

路由模块化 #

使用模块组织路由 #

typescript
// users.module.ts
@Module({
  controllers: [UsersController],
})
export class UsersModule {}

// app.module.ts
@Module({
  imports: [UsersModule],
})
export class AppModule {}

路由前缀 #

typescript
// main.ts
app.setGlobalPrefix('api/v1');

// 所有路由添加前缀
// /api/v1/users
// /api/v1/products

排除路由 #

typescript
app.setGlobalPrefix('api', {
  exclude: ['health', 'metrics'],
});

路由守卫 #

在路由级别应用守卫:

typescript
@Controller('users')
@UseGuards(AuthGuard)
export class UsersController {
  @Get()
  findAll() {}

  @Get('public')
  @Public()
  getPublicData() {}
}

路由中间件 #

typescript
@Controller('users')
@UseMiddleware(LoggerMiddleware)
export class UsersController {
  @Get()
  findAll() {}
}

路由拦截器 #

typescript
@Controller('users')
@UseInterceptors(LoggingInterceptor)
export class UsersController {
  @Get()
  findAll() {}
}

路由重定向 #

typescript
@Get('docs')
@Redirect('https://docs.nestjs.com', 302)
getDocs() {}

@Get('redirect')
@Redirect()
redirectTo() {
  return {
    url: 'https://nestjs.com',
    statusCode: 301,
  };
}

路由渲染 #

使用模板引擎渲染视图:

typescript
import { Render } from '@nestjs/common';

@Controller()
export class AppController {
  @Get()
  @Render('index')
  root() {
    return { message: 'Hello World!' };
  }
}

路由最佳实践 #

1. RESTful设计 #

typescript
@Controller('users')
export class UsersController {
  @Get()           // 获取列表
  findAll() {}

  @Get(':id')      // 获取单个
  findOne() {}

  @Post()          // 创建
  create() {}

  @Put(':id')      // 完整更新
  update() {}

  @Patch(':id')    // 部分更新
  partialUpdate() {}

  @Delete(':id')   // 删除
  remove() {}
}

2. 资源嵌套 #

typescript
// 用户下的文章
@Controller('users/:userId/posts')
export class UserPostsController {
  @Get()
  findAll(@Param('userId') userId: string) {}

  @Get(':id')
  findOne(
    @Param('userId') userId: string,
    @Param('id') id: string,
  ) {}
}

3. 路由命名规范 #

操作 路由 方法
获取列表 /users GET
获取单个 /users/:id GET
创建 /users POST
更新 /users/:id PUT/PATCH
删除 /users/:id DELETE

路由调试 #

查看所有路由 #

typescript
import { DiscoveryService, RouteInfo } from '@nestjs/core';

@Injectable()
export class RoutesService {
  constructor(private discoveryService: DiscoveryService) {}

  getRoutes(): RouteInfo[] {
    return this.discoveryService.getControllers();
  }
}

路由日志 #

typescript
const app = await NestFactory.create(AppModule, {
  logger: ['log', 'error', 'warn', 'debug', 'verbose'],
});

总结 #

本章学习了NestJS路由基础:

  • 路由定义和装饰器
  • 路由匹配规则
  • 路由参数处理
  • 路由模块化组织
  • 版本控制和路由分组

接下来,让我们学习 请求参数处理

最后更新:2026-03-28