nestJs 控制器
参考:
https://docs.nestjs.cn/9/controllers
控制器负责处理传入的请求和向客户端返回响应。
控制器的目的是接收应用的特定请求。路由机制控制哪个控制器接收哪些请求。通常,每个控制器有多个路由,不同的路由可以执行不同的操作。
为了创建一个基本的控制器,我们使用类和装饰器
。
装饰器将类与所需的元数据相关联,并使 Nest 能够创建路由映射(将请求绑定到相应的控制器)。
创建控制器
我们先使用 nestCli
工具创建
nest g controller cats
可以看到他是,创建了两个文件,并且更新了一个文件
我们看下他更新的这个文件,更新了什么
可以看到增加了这些东西
至于 cats.controller.spec.ts
是自动生成的单元测试样例,可要可不要
重要的是 cats.controller.ts
这个文件,我们看下这个文件
import { Controller } from '@nestjs/common';
@Controller('cats')
export class CatsController {}
可以看到就几行代码,一目了然,那后面我们创建控制器,可以采用更方便的方式
直接创建一个文件,并修改下 app.module.ts
文件即可,该文件是应用模块根模块
路由
在下面的例子中
我们使用 @Controller()
装饰器定义一个基本的控制器。可选 路由路径前缀设置为 cats
。
在 @Controller()
装饰器中使用路径前缀可以使我们轻松地对一组相关的路由进行分组
并最大程度地减少重复代码。
例如
我们可以选择将一组用于管理与 /customers
下的客户实体进行互动的路由进行分组。
这样
我们可以在 @Controller()
装饰器中指定路径前缀 customers
这样就不必为文件中的每个路由重复路径的那部分。
import { Controller, Get } from '@nestjs/common';
// 装饰器
// 声明控制器,添加了路由组(路由前缀) cats
@Controller('cats')
export class CatsController {
// 绑定到控制器方法, 此时路由为:/cats//customer
@Get('/customer')
findAll(): string {
return 'This action returns all cats';
}
}
此函数将返回 200
状态代码和相关的响应,在本例中只返回了一个字符串。为什么会这样? 为了解释原因,首先我们将介绍 Nest 使用两种不同的操作响应选项的概念:
标准(推荐) | 使用这个内置方法,当请求处理程序返回一个 JavaScript 对象或数组时,它将自动序列化为 JSON 。但是,当它返回一个 JavaScript 基本类型(例如string、number、boolean )时, Nest 将只发送值,而不尝试序列化它。这使响应处理变得简单:只需要返回值,其余的由 Nest 负责。 |
类库特有的 | 我们可以在函数签名处通过 @Res() 注入类库特定的响应对象(例如, Express )。使用此方法,你就能使用由该响应对象暴露的原生响应处理函数。例如,使用 Express ,您可以使用 response.status(200).send() 构建响应 |
注意!Nest 检测处理程序何时使用
@Res()
或@Next()
,表明你选择了特定于库的选项。如果在一个处理函数上同时使用了这两个方法,那么此处的标准方式就是自动禁用此路由, 你将不会得到你想要的结果。如果需要在某个处理函数上同时使用这两种方法(例如,通过注入响应对象,单独设置 cookie / header,但把其余部分留给框架),你必须在装饰器@Res({ passthrough: true })
中将passthrough
选项设为true
Request
NestJs 提供了方法参数装饰器,用来帮助我们快速获取参数 如下
装饰器 | 参数 |
---|---|
@Request(),@Req() |
req |
@Response(),@Res()* |
res |
@Next() |
next |
@Session() |
req.session |
@Param(key?: string) |
req.params /req.params[key] |
@Body(key?: string) |
req.body /req.body[key] |
@Query(key?: string) |
req.query /req.query[key] |
@Headers(name?: string) |
req.headers /req.headers[name] |
@Ip() |
req.ip |
@HostParam() |
req.hosts |
获取get请求传参
可以使用 Request
装饰器 或者 Query
装饰器
通过Request装饰器
例:
import { Controller, Get, Request } from '@nestjs/common';
// 装饰器
// 声明控制器,添加了路由组(路由前缀) cats
@Controller('cats')
export class CatsController {
// 绑定到控制器方法, 此时路由为:/cats//customer
@Get('/customer')
findAll(@Request() req:any): string {
console.log("req ===========>", req.query);
return 'This action returns all cats';
}
}
通过Query装饰器
也可以使用Query 直接获取 不需要在通过req.query 了
例:
import { Controller, Get, Query } from '@nestjs/common';
// 装饰器
// 声明控制器,添加了路由组(路由前缀) cats
@Controller('cats')
export class CatsController {
// 绑定到控制器方法, 此时路由为:/cats//customer
@Get('/customer')
findAll(@Query() query): string {
console.log("query ===========>", query);
return 'This action returns all cats';
}
}
输出结果跟上面一致
post 获取参数
可以使用Request
装饰器 或者 Body
装饰器
raw json 格式
通过Request装饰器
import { Controller, Request, Post } from '@nestjs/common';
// 装饰器
// 声明控制器,添加了路由组(路由前缀) cats
@Controller('cats')
export class CatsController {
// 绑定到控制器方法, 此时路由为:/cats//customer
@Post('/customer')
findAll(@Request() request): string {
console.log("request.body ===========>", request.body);
return 'This action returns all cats';
}
}
通过Body 装饰器
import { Controller, Request, Post, Body } from '@nestjs/common';
// 装饰器
// 声明控制器,添加了路由组(路由前缀) cats
@Controller('cats')
export class CatsController {
// 绑定到控制器方法, 此时路由为:/cats//customer
@Post('/customer')
findAll(@Body() body): string {
console.log("body ===========>", body);
return 'This action returns all cats';
}
}
直接读取key 也可以
import { Controller, Request, Post, Body } from '@nestjs/common';
// 装饰器
// 声明控制器,添加了路由组(路由前缀) cats
@Controller('cats')
export class CatsController {
// 绑定到控制器方法, 此时路由为:/cats//customer
@Post('/customer')
findAll(@Body('name') name): string {
console.log("name ===========>", name);
return 'This action returns all cats';
}
}
获取 multipart/form-data
格式 数据
如果表单数据是 multipart/form-data
格式,
那么可以使用 @UploadedFile()
装饰器来获取上传的文件。
同时,也可以使用 @Body()
装饰器来获取除文件外的表单数据。
其中,
@UseInterceptors(FileInterceptor('file'))
装饰器用于将上传的文件注入到 file
参数中,
@Body()
装饰器用于将表单数据注入到 formData
参数中。
需要注意的是,
@UseInterceptors
装饰器需要使用 @nestjs/platform-express
包中提供的 FileInterceptor
中间件,该中间件会将上传的文件保存到临时目录中,并将文件信息注入到 file
参数中。
案例
import { Controller, Request, Post, Body, UseInterceptors, UploadedFile } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
// 装饰器
// 声明控制器,添加了路由组(路由前缀) cats
@Controller('cats')
export class CatsController {
// 绑定到控制器方法, 此时路由为:/cats//customer
@Post('/customer')
@UseInterceptors(FileInterceptor('file'))
findAll(@UploadedFile() file: Express.Multer.File, @Body() formData): string {
console.log("file --------->", file);
console.log("formData --------->", formData);
return 'This action returns all cats';
}
}
命名空间“global.Express”没有已导出的成员“Multer”。
如果出现
这个问题
这个问题通常是由于缺少依赖包 @types/multer
导致的,你可以通过以下命令安装此依赖包:
npm install --save-dev @types/multer
如果问题仍然存在,可以尝试清除缓存并重新安装依赖包:
npm cache clean --force
rm -rf node_modules
npm install
如果还是不行,可以尝试升级 @types/express
的版本,因为 @types/multer
依赖于 @types/express
。你可以通过以下命令升级 @types/express
:
npm install --save-dev @types/express@latest
获取动态路由参数
可以使用Request装饰器 或者 Param 装饰器 跟express 完全一样
通过Request装饰器
例:
import { Controller, Request, Post, Body, UseInterceptors, UploadedFile, Get } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
// 装饰器
// 声明控制器,添加了路由组(路由前缀) cats
@Controller('cats')
export class CatsController {
// 绑定到控制器方法, 此时路由为:/cats/customer
@Get('/customer/:id')
findAll(@Request() req): string {
console.log("file --------->", req);
return 'This action returns all cats';
}
}
请求:
http://localhost:3000/cats/customer/1314
结果
通过 params装饰器
import { Controller, Request, Post, Body, UseInterceptors, UploadedFile, Get, Param } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
// 装饰器
// 声明控制器,添加了路由组(路由前缀) cats
@Controller('cats')
export class CatsController {
// 绑定到控制器方法, 此时路由为:/cats/customer
@Get('/customer/:id')
findAll(@Param() param): string {
console.log("param --------->", param);
return 'This action returns all cats';
}
}
请求:
http://localhost:3000/cats/customer/1314
结果
获取header 信息
@Headers() headers
例:
import { Controller, Headers, Post, Body, UseInterceptors, UploadedFile, Get, Param } from '@nestjs/common';
// 装饰器
// 声明控制器,添加了路由组(路由前缀) cats
@Controller('cats')
export class CatsController {
// 绑定到控制器方法, 此时路由为:/cats/customer
@Get('/customer/:id')
findAll(@Headers() headers): string {
console.log("headers --------->", headers);
return 'This action returns all cats';
}
}
状态码
使用 HttpCode
装饰器 控制接口返回的状态码
import { Controller, Headers, Post, Body, UseInterceptors, UploadedFile, Get, Param, HttpCode } from '@nestjs/common';
// 装饰器
// 声明控制器,添加了路由组(路由前缀) cats
@Controller('cats')
export class CatsController {
// 绑定到控制器方法, 此时路由为:/cats/customer
@Get('/customer/')
@HttpCode(500)
findAll(@Headers() headers): string {
return 'This action returns all cats';
}
}
结果