控制器负责处理传入的请求并将响应返回给客户端。而路由的职责用于执行匹配路由后的逻辑,一个Controller可以可以有多个路由。Nest提供了一系列装饰器用于处理请求与响应,学习过这些装饰器后一切将变得非常简单。

1.@Controller标识当前类是一个控制器

@Controller装饰器标识当前类是一个控制器,@Controller可以指定一个路径前缀,用于控制器分组。

  1. /*
  2. * 不加路径前缀的Controller例子,假设应用端口为3000
  3. */
  4. import {Controller,Get} from '@nestjs/common';
  5. @Controller
  6. export class AppController {
  7. /*
  8. * 访问localhost:3000/findUser即可成功调用接口
  9. */
  10. @Get("/findUser")
  11. findUser():object{
  12. return {name:"zxp",id:1}
  13. }
  14. }
  15. /*
  16. * 加路径前缀的Controller例子,假设应用端口为3000
  17. */
  18. import {Controller} from '@nestjs/common';
  19. @Controller("/user")
  20. export class AppController {
  21. /*
  22. * 访问localhost:3000/user/findUser即可成功调用接口
  23. */
  24. @Get("/findUser")
  25. findUser():object{
  26. return {name:"zxp",id:1}
  27. }
  28. }

2.@Get、@Post处理不同请求类型路由

这些装饰器用于处理请求路由:
@Get用于处理指定路由的GET请求。若以其他请求类型访问@Get路由则会报404错误。
@Post用于处理指定路由的POST请求。若以其他请求类型访问@Post路由则会报404错误。还有其他请求类型,非常简单没什么好说。

3.@Request和@Req获取Request对象

@Requst和@Req注解用于获取请求对象,@Request与@Req作用是一样的,@Req是@Request的简写。通过请求对象可以获取请求的query、param、body、headers、ip、host等信息,@Query、@Param、@Body等装饰器是对请求对象进一步封装。请求对象的类型取决你用的web框架,如果你使用的express就从express包导入,使用的web框架是fastify就从fastify导入Request对象。

  1. import {Controller,Req,Get} from '@nestjs/common';
  2. @Controller
  3. export class AppController {
  4. @Get("/getReq")
  5. getReq(@Req() req):Request{
  6. /**
  7. * 假设访问localhost:3000/getReq?name=zxp
  8. */
  9. console.log('query:', req.query); //query: { name: 'zxp' }
  10. console.log('params:', req.params);
  11. console.log('body:', req.body);
  12. console.log('headers:', req.headers);
  13. console.log('ip:', req.ip); //ip: ::1
  14. console.log('host:', req.host); //host: localhost
  15. return req;
  16. }
  17. }

4.@Query获取请求查询参数

@Query注解用于获取请求URL上的查询参数,也就是请求url中?号后面的参数。

  1. import {Controller,Req,Get,Query} from '@nestjs/common';
  2. @Controller
  3. export class AppController {
  4. //@Query写法1:参数写法,允许为参数添加类型,这一点是很重要的,推荐这种写法
  5. @Get("/getQueryParams")
  6. getQueryParams(@Query() id:number):string{
  7. //假设访问localhost:3000/getQueryParams?id=1
  8. console.log(id); //1
  9. return "参数是:"+id;
  10. }
  11. //@Query写法2:结构写法,参数无法添加类型,但是很方便
  12. @Get("/getUser")
  13. getUser(@Query(){id}):string{
  14. //假设访问localhost:3000/getQueryParams?id=1
  15. console.log(id); //1
  16. return "参数是:"+id;
  17. }
  18. }

5.@Param获取路由参数

@Param装饰器用于获取路由上的参数,一般用于获取动态路由的参数。

  1. import {Controller,Get,Param} from '@nestjs/common';
  2. @Controller
  3. export class AppController {
  4. @Get("/getParams/:id")
  5. getParams(@Param() id:number):number{
  6. //假设访问localhost:3000/getParams/1
  7. console.log(id);//1
  8. return "获取param参数为:"+id;
  9. }
  10. }

6.@Body获取表单数据

@Body可以获取以x-www-form-urlencoded和raw格式提交的数据。

  1. import {Controller,Post,Body} from '@nestjs/common';
  2. @Controller
  3. export class AppController {
  4. @Post("/addUser")
  5. addUser(@Body() data):object{
  6. console.log(data);
  7. return data
  8. }
  9. }

效果图:
啦啦啦;.gif

7.@Response和@Res获取响应对象

@Response和@Res可以获取响应对象,@Res和@Response具有一样的作用,@Res是@Response的简写,通过响应对象可以设置响应状态码、响应数据格式等等。

  1. import {Controller,Get,Res,HttpStatus} from '@nestjs/common';
  2. import { Response} from 'express';
  3. @Controller
  4. export class AppController {
  5. /*
  6. * 响应状态码为200并以json格式响应。
  7. */
  8. @Get("/findUser")
  9. findUser(@Res() res):Response{
  10. return res.status(HttpStatus.OK).json({name:"zxp"});
  11. }
  12. }

8.@Headers获取请求头信息

  1. import {Controller,Get,Headers} from '@nestjs/common';
  2. @Controller
  3. export class AppController {
  4. @Get("/getUser")
  5. getUser(@Headers() headers){
  6. const obj = {
  7. 'user-agent': 'PostmanRuntime/7.26.3',
  8. accept: '*/*',
  9. 'postman-token': '1e4c5aa7-918c-4363-bc13-bbfcce27565e',
  10. host: 'localhost:3000',
  11. 'accept-encoding': 'gzip, deflate, br',
  12. connection: 'keep-alive',
  13. };
  14. return header; // 结果为obj的内容
  15. }
  16. }

9.@Redirect转发路由

@Redirect装饰器用于请求转发。

  1. import {Controller,Get,Redirect} from '@nestjs/common';
  2. @Controller
  3. export class AppController {
  4. @Get("/redirect")
  5. @Redirect("http://localhost:3000/getUser") //转发到/getUser路由
  6. redirect(){
  7. console.log("转发请求...");
  8. }
  9. @Get("/getUser")
  10. getUser():object{
  11. return {name:"zxp'}
  12. }
  13. }

10.@HttpCode设置响应状态码,@Header用于设置响应头

@HttpCode用于设置响应状态码,如果不显示设置响应状态码则默认是200。

  1. import {Controller,Get,HttpCode,Header} from '@nestjs/common';
  2. @Controller
  3. export class AppController {
  4. //当访问localhost:3000/setResCode时状态码为204 No Content
  5. @Get("/setResCode")
  6. @HttpCode(204)
  7. @Header('Cache-Control', 'none') //设置响应头,表示不开启缓存
  8. setHttpCode(){
  9. return "204..."
  10. }
  11. }

11.@Bind用于将包装的装饰器绑定到路由方法的参数

@Bind装饰器的作用是将包装的装饰器绑定到路由方法的参数,这样可以不用在路由方法中使用装饰器而获得同样的功能。

  1. import {Controller,Get,Req,Res,Query} from '@nestjs/common';
  2. @Controller
  3. export class AppController {
  4. @Bind(Req(),Res(), Query())
  5. bind(req,res, query) {
  6. console.log('请求对象:', req);
  7. console.log('响应对象:', res);
  8. console.log('请求查询参数对象:', query);
  9. }
  10. }

完整的例子:

  1. import {
  2. Controller,
  3. Get,
  4. Query,
  5. Req,
  6. Post,
  7. Body,
  8. Param,
  9. Delete,
  10. Res,
  11. HttpCode,
  12. Headers,
  13. Ip,
  14. Redirect,
  15. Header,
  16. HttpStatus,
  17. Session,
  18. Bind
  19. } from '@nestjs/common';
  20. import { Request,Response} from 'express';
  21. import { AppService } from './app.service';
  22. const data = [];
  23. for (let i = 0; i < 100; i++) {
  24. data.push({
  25. id: i,
  26. name: `user-${i}`,
  27. });
  28. }
  29. /**
  30. * @Controller可以接收一个参数用于区分路由分组
  31. */
  32. @Controller()
  33. export class AppController {
  34. constructor(private readonly appService: AppService) {}
  35. @Get('/hello')
  36. getHello(): string {
  37. return this.appService.getHello();
  38. }
  39. /**
  40. * @Query装饰器用于获取请求url的查询参数(?号后面的参数),@Query相当于@Req的res.query,@Query有两种写法:
  41. * 第一种是正常的方法写法,例如@Query(id:number,name:string),这种写法可以使用ts指定参数类型(推荐)。
  42. * 第二种是结构写法,例如@Query(){id,name},这种写法无法使用ts指定参数类型。
  43. *
  44. * 访问 http://localhost:3000/findUser?id=1&name=user-1
  45. * 结果为: {"id":1,"name":"user-1"}
  46. */
  47. @Get('/findUser')
  48. findUser(@Query() { id, name }): object {
  49. return data.filter(
  50. (item) => item.id == id && item.name.indexOf(name) > -1,
  51. )[0];
  52. }
  53. /**
  54. *
  55. * @Body可以获取以x-www-form-urlencoded和raw格式提交的数据
  56. */
  57. @Post('/addUser')
  58. addUser(@Body() body): object {
  59. /**
  60. * 假设使用Postman以raw格式提交的数据内容为{"id":1}
  61. */
  62. console.log(body); //{id:1}
  63. return body;
  64. }
  65. /**
  66. * @Param可以获取请求URL中的参数,一般用于获取动态参数,
  67. * 例如访问localhost:3000/1,下面例子中id的值为1
  68. */
  69. @Delete(':id')
  70. delUser(@Param() { id }): string {
  71. console.log(id); //1
  72. return '删除成功';
  73. }
  74. /**
  75. * @Headers 用于获取请求头对象
  76. */
  77. @Get('/getHeader')
  78. getHeader(@Headers() header): object {
  79. const obj = {
  80. 'user-agent': 'PostmanRuntime/7.26.3',
  81. accept: '*/*',
  82. 'postman-token': '1e4c5aa7-918c-4363-bc13-bbfcce27565e',
  83. host: 'localhost:3000',
  84. 'accept-encoding': 'gzip, deflate, br',
  85. connection: 'keep-alive',
  86. };
  87. return header; // 结果为obj的内容
  88. }
  89. /**
  90. * @Header装饰器用于设置响应头信息。
  91. * @Ip装饰器用于获取请求ip。
  92. */
  93. @Get('/getIp')
  94. @Header('Cache-Control', 'none')
  95. getIp(@Ip() ip): string {
  96. return '请求ip为:' + ip; //请求ip为:::1
  97. }
  98. /**
  99. * @Session用于获取请求Session信息
  100. */
  101. @Get('/getSession')
  102. getSession(@Session() session) {
  103. return 'session:' + session;
  104. }
  105. /**
  106. * @HttpCode装饰器用于设置响应状态码,如不显示设置默认为200,
  107. * 当访问localhost:3000/setResCode时状态码为204 No Content
  108. */
  109. @Post('/setResCode')
  110. @HttpCode(204)
  111. setResCode(): string {
  112. return '响应成功';
  113. }
  114. /**
  115. *@Redirect装饰器用于路由转发
  116. */
  117. @Get('/redirect')
  118. @Redirect('http://localhost:3000/findAll', 200)
  119. redirect() {
  120. return '转发成功';
  121. }
  122. /**
  123. * @Request和@Req装饰器用于设置请求对象,@Req是@Request的简写,它们的作用都是一样的,
  124. * 通过请求对象可以获取到query、param、body、ip、headers、host、hosts等参数,
  125. * 像@Query、@Param、@Body、@Ip等等这些装饰器都是对请求对象进一步封装。
  126. */
  127. @Get('/findAll')
  128. findAll(@Req() req): Request {
  129. /**
  130. * 假设访问localhost:3000/findAll?name=zxp
  131. */
  132. console.log('query:', req.query); //query: { name: 'zxp' }
  133. console.log('params:', req.params);
  134. console.log('body:', req.body);
  135. console.log('headers:', req.headers);
  136. console.log('ip:', req.ip); //ip: ::1
  137. console.log('host:', req.host); //host: localhost
  138. return req;
  139. }
  140. /**
  141. * @Response和@Res装饰器用于设置响应对象,@Res装饰器是@Response的简写,它们的作用是一样的
  142. * 通过响应对象你可以设置响应状态码、响应格式等等。
  143. * res.status(HttpStatus.OK) 用于设置响应状态码为200,
  144. * json()用于将数据转为json格式
  145. */
  146. @Get('/findList')
  147. findList(@Res() res) {
  148. return res.status(HttpStatus.OK).json({ name: 'zxp', id: 1 });
  149. }
  150. /**
  151. * @Bind装饰器的作用是将包装的装饰器绑定到路由方法的参数,这样可以不用在路由方法中使用装饰器
  152. * 而获得同样的功能。
  153. */
  154. @Bind(Req(), Query())
  155. bind(req, query) {
  156. console.log('请求对象:', req);
  157. console.log('请求查询参数对象:', query);
  158. }
  159. }