nestjs @Param 从入门到精通
一、基础入门:提取单个路由参数
-
定义路由参数
在控制器方法中,使用:paramName
语法声明路径参数:import { Controller, Get, Param } from '@nestjs/common';@Controller('users') export class UsersController {@Get(':id')findOne(@Param('id') id: string) {return `User ID: ${id}`; // 访问 /users/123 返回 "User ID: 123"} }
-
参数类型处理
- 默认返回字符串类型,如需数字或其他类型,需手动转换:
@Get(':id') findOne(@Param('id') id: string) {const numericId = parseInt(id, 10); // 转为数字return `Numeric ID: ${numericId}`; }
- 默认返回字符串类型,如需数字或其他类型,需手动转换:
二、进阶技巧:批量提取与类型安全
-
批量提取所有参数
直接使用@Param()
不传参数,获取所有路由参数的键值对:@Get(':userId/posts/:postId') findPost(@Param() params: { userId: string; postId: string }) {return `User ${params.userId}'s Post ${params.postId}`; }
-
结合 DTO 实现类型安全
通过自定义类或接口定义参数结构:interface RouteParams {userId: string;postId: string; }@Get(':userId/posts/:postId') findPost(@Param() params: RouteParams) {return `User ${params.userId}'s Post ${params.postId}`; }
三、高级应用:参数验证与嵌套路由
-
参数验证(结合
@nestjs/validated
)
使用class-validator
和class-transformer
验证参数:import { IsNumberString } from 'class-validator';class UserParams {@IsNumberString()id: string; }@Get(':id') findOne(@Param() params: UserParams) {// 若 id 非数字,自动返回 400 错误return `Valid User ID: ${params.id}`; }
-
嵌套路由中的参数提取
在模块化路由中,参数会逐级传递:// 模块路由:/api/users/:userId/orders/:orderId @Controller('users/:userId/orders') export class OrdersController {@Get(':orderId')findOrder(@Param('userId') userId: string,@Param('orderId') orderId: string,) {return `Order ${orderId} of User ${userId}`;} }
四、最佳实践:错误处理与性能优化
-
参数缺失的默认处理
NestJS 会自动返回 404 错误,若需自定义响应:@Get(':id') findOne(@Param('id') id: string) {if (!id) {throw new NotFoundException('ID is required');}return `User ID: ${id}`; }
-
性能优化:缓存参数解析结果
对频繁访问的参数,可在服务层缓存解析结果:@Injectable() export class UsersService {private cache = new Map<string, any>();findOne(id: string) {if (this.cache.has(id)) {return this.cache.get(id);}const user = { id, name: 'Example' }; // 模拟数据库查询this.cache.set(id, user);return user;} }
五、常见问题与解决方案
-
问题:参数未提取到
- 检查路由路径是否包含
:paramName
。 - 确保请求 URL 与路由定义匹配(如
/users/1
而非/users?id=1
)。
- 检查路由路径是否包含
-
问题:参数类型错误
- 显式转换类型(如
parseInt(id, 10)
)。 - 使用
class-validator
进行严格验证。
- 显式转换类型(如
-
问题:嵌套路由参数冲突
- 避免不同层级使用相同参数名(如
/users/:id/posts/:id
会冲突)。
- 避免不同层级使用相同参数名(如
六、完整示例:RESTful API 实现
import { Controller, Get, Param, Post, Body, NotFoundException } from '@nestjs/common';interface CreateUserDto {name: string;email: string;
}@Controller('users')
export class UsersController {private users = [{ id: '1', name: 'Alice', email: 'alice@example.com' }];@Get(':id')findOne(@Param('id') id: string) {const user = this.users.find(u => u.id === id);if (!user) {throw new NotFoundException('User not found');}return user;}@Post()create(@Body() userData: CreateUserDto) {const newUser = {id: Date.now().toString(),...userData,};this.users.push(newUser);return newUser;}
}