nestjs @Get 从入门到精通
一、基础入门:静态路由与简单响应
-
定义基础 GET 路由
使用@Controller()
指定路由前缀,@Get()
定义方法路径:import { Controller, Get } from '@nestjs/common';@Controller('cats') export class CatsController {@Get()findAll(): string {return 'This action returns all cats'; // 访问 /cats 返回字符串} }
-
返回 JSON 数据
NestJS 自动将对象序列化为 JSON:@Get() findAll(): { name: string; age: number }[] {return [{ name: 'Whiskers', age: 3 }, { name: 'Fluffy', age: 5 }]; }
二、进阶技巧:动态路由与查询参数
-
动态路由参数
通过:param
语法提取路径中的动态参数,结合@Param()
获取值:import { Param } from '@nestjs/common';@Get(':id') findOne(@Param('id') id: string): string {return `Cat ID: ${id}`; // 访问 /cats/123 返回 "Cat ID: 123" }
-
查询字符串参数
使用@Query()
获取 URL 查询参数(如?name=Whiskers
):import { Query } from '@nestjs/common';@Get('search') search(@Query('name') name: string): string {return `Searching for cat named ${name}`; // 访问 /cats/search?name=Whiskers }
-
批量提取查询参数
直接使用@Query()
不传参数,获取所有查询参数的键值对:@Get('filter') filter(@Query() filters: { age?: number; color?: string }): string {return `Filtered by: ${JSON.stringify(filters)}`; }
三、高级应用:路由重定向与元数据
-
路由重定向
使用@Redirect()
将请求重定向到其他 URL:import { Redirect } from '@nestjs/common';@Get('old') @Redirect('/cats/new', 301) // 301 永久重定向 redirectToNew() {return { url: '/cats/new' }; }
-
设置元数据
通过@SetMetadata()
添加路由元数据,用于后续拦截器或守卫处理:import { SetMetadata } from '@nestjs/common';@Get('admin') @SetMetadata('roles', ['admin']) // 标记需要管理员权限 adminDashboard() {return 'Admin Dashboard'; }
四、最佳实践:代码组织与性能优化
-
模块化路由
将相关路由拆分到不同控制器,并通过@Module()
导入:// cats.controller.ts @Controller('cats') export class CatsController { /* ... */ }// app.module.ts @Module({imports: [],controllers: [CatsController], // 注册控制器providers: [], }) export class AppModule {}
-
统一前缀管理
通过app.setGlobalPrefix()
为所有路由添加公共前缀(如/api
):// main.ts import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module';async function bootstrap() {const app = await NestFactory.create(AppModule);app.setGlobalPrefix('api'); // 所有路由前缀变为 /api/catsawait app.listen(3000); } bootstrap();
-
性能优化:缓存响应
使用@CacheInterceptor()
缓存频繁访问的 GET 请求结果:import { CacheInterceptor, Controller, Get, UseInterceptors } from '@nestjs/common';@Controller('cats') @UseInterceptors(CacheInterceptor) // 启用缓存 export class CatsController {@Get('popular')findPopularCats() {return ['Whiskers', 'Fluffy']; // 结果会被缓存} }
五、常见问题与解决方案
-
问题:路由冲突
- 原因:多个路由匹配同一路径(如
/cats/:id
和/cats/new
)。 - 解决:调整路由顺序,将静态路径(如
/new
)放在动态路径(如/:id
)之前。
- 原因:多个路由匹配同一路径(如
-
问题:参数类型错误
- 原因:
@Param('id')
默认返回字符串,需手动转换类型。 - 解决:在服务层转换类型或使用
class-validator
验证:import { IsNumberString } from 'class-validator';class GetCatDto {@IsNumberString()id: string; }@Get(':id') findOne(@Param() params: GetCatDto) {const numericId = parseInt(params.id, 10);return `Numeric ID: ${numericId}`; }
- 原因:
-
问题:跨域请求(CORS)
- 解决:在
main.ts
中启用 CORS:async function bootstrap() {const app = await NestFactory.create(AppModule);app.enableCors(); // 允许所有跨域请求await app.listen(3000); }
- 解决:在
六、完整示例:RESTful API 实现
import { Controller, Get, Param, Query, CacheInterceptor, UseInterceptors } from '@nestjs/common';@Controller('cats')
@UseInterceptors(CacheInterceptor) // 启用缓存
export class CatsController {// 静态路由@Get()findAll(): string[] {return ['Whiskers', 'Fluffy', 'Mittens'];}// 动态路由@Get(':id')findOne(@Param('id') id: string): string {return `Cat ID: ${id}`;}// 查询参数@Get('search')search(@Query('name') name: string): string {return `Searching for: ${name}`;}// 批量查询参数@Get('filter')filter(@Query() filters: { age?: number; color?: string }): string {return `Filtered by: ${JSON.stringify(filters)}`;}
}