控制器负责处理传入的请求并将响应返回给客户端。而路由的职责用于执行匹配路由后的逻辑,一个Controller可以可以有多个路由。Nest提供了一系列装饰器用于处理请求与响应,学习过这些装饰器后一切将变得非常简单。
1.@Controller标识当前类是一个控制器
@Controller装饰器标识当前类是一个控制器,@Controller可以指定一个路径前缀,用于控制器分组。
/** 不加路径前缀的Controller例子,假设应用端口为3000*/import {Controller,Get} from '@nestjs/common';@Controllerexport class AppController {/** 访问localhost:3000/findUser即可成功调用接口*/@Get("/findUser")findUser():object{return {name:"zxp",id:1}}}/** 加路径前缀的Controller例子,假设应用端口为3000*/import {Controller} from '@nestjs/common';@Controller("/user")export class AppController {/** 访问localhost:3000/user/findUser即可成功调用接口*/@Get("/findUser")findUser():object{return {name:"zxp",id:1}}}
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对象。
import {Controller,Req,Get} from '@nestjs/common';@Controllerexport class AppController {@Get("/getReq")getReq(@Req() req):Request{/*** 假设访问localhost:3000/getReq?name=zxp*/console.log('query:', req.query); //query: { name: 'zxp' }console.log('params:', req.params);console.log('body:', req.body);console.log('headers:', req.headers);console.log('ip:', req.ip); //ip: ::1console.log('host:', req.host); //host: localhostreturn req;}}
4.@Query获取请求查询参数
@Query注解用于获取请求URL上的查询参数,也就是请求url中?号后面的参数。
import {Controller,Req,Get,Query} from '@nestjs/common';@Controllerexport class AppController {//@Query写法1:参数写法,允许为参数添加类型,这一点是很重要的,推荐这种写法@Get("/getQueryParams")getQueryParams(@Query() id:number):string{//假设访问localhost:3000/getQueryParams?id=1console.log(id); //1return "参数是:"+id;}//@Query写法2:结构写法,参数无法添加类型,但是很方便@Get("/getUser")getUser(@Query(){id}):string{//假设访问localhost:3000/getQueryParams?id=1console.log(id); //1return "参数是:"+id;}}
5.@Param获取路由参数
@Param装饰器用于获取路由上的参数,一般用于获取动态路由的参数。
import {Controller,Get,Param} from '@nestjs/common';@Controllerexport class AppController {@Get("/getParams/:id")getParams(@Param() id:number):number{//假设访问localhost:3000/getParams/1console.log(id);//1return "获取param参数为:"+id;}}
6.@Body获取表单数据
@Body可以获取以x-www-form-urlencoded和raw格式提交的数据。
import {Controller,Post,Body} from '@nestjs/common';@Controllerexport class AppController {@Post("/addUser")addUser(@Body() data):object{console.log(data);return data}}
7.@Response和@Res获取响应对象
@Response和@Res可以获取响应对象,@Res和@Response具有一样的作用,@Res是@Response的简写,通过响应对象可以设置响应状态码、响应数据格式等等。
import {Controller,Get,Res,HttpStatus} from '@nestjs/common';import { Response} from 'express';@Controllerexport class AppController {/** 响应状态码为200并以json格式响应。*/@Get("/findUser")findUser(@Res() res):Response{return res.status(HttpStatus.OK).json({name:"zxp"});}}
8.@Headers获取请求头信息
import {Controller,Get,Headers} from '@nestjs/common';@Controllerexport class AppController {@Get("/getUser")getUser(@Headers() headers){const obj = {'user-agent': 'PostmanRuntime/7.26.3',accept: '*/*','postman-token': '1e4c5aa7-918c-4363-bc13-bbfcce27565e',host: 'localhost:3000','accept-encoding': 'gzip, deflate, br',connection: 'keep-alive',};return header; // 结果为obj的内容}}
9.@Redirect转发路由
@Redirect装饰器用于请求转发。
import {Controller,Get,Redirect} from '@nestjs/common';@Controllerexport class AppController {@Get("/redirect")@Redirect("http://localhost:3000/getUser") //转发到/getUser路由redirect(){console.log("转发请求...");}@Get("/getUser")getUser():object{return {name:"zxp'}}}
10.@HttpCode设置响应状态码,@Header用于设置响应头
@HttpCode用于设置响应状态码,如果不显示设置响应状态码则默认是200。
import {Controller,Get,HttpCode,Header} from '@nestjs/common';@Controllerexport class AppController {//当访问localhost:3000/setResCode时状态码为204 No Content@Get("/setResCode")@HttpCode(204)@Header('Cache-Control', 'none') //设置响应头,表示不开启缓存setHttpCode(){return "204..."}}
11.@Bind用于将包装的装饰器绑定到路由方法的参数
@Bind装饰器的作用是将包装的装饰器绑定到路由方法的参数,这样可以不用在路由方法中使用装饰器而获得同样的功能。
import {Controller,Get,Req,Res,Query} from '@nestjs/common';@Controllerexport class AppController {@Bind(Req(),Res(), Query())bind(req,res, query) {console.log('请求对象:', req);console.log('响应对象:', res);console.log('请求查询参数对象:', query);}}
完整的例子:
import {Controller,Get,Query,Req,Post,Body,Param,Delete,Res,HttpCode,Headers,Ip,Redirect,Header,HttpStatus,Session,Bind} from '@nestjs/common';import { Request,Response} from 'express';import { AppService } from './app.service';const data = [];for (let i = 0; i < 100; i++) {data.push({id: i,name: `user-${i}`,});}/*** @Controller可以接收一个参数用于区分路由分组*/@Controller()export class AppController {constructor(private readonly appService: AppService) {}@Get('/hello')getHello(): string {return this.appService.getHello();}/*** @Query装饰器用于获取请求url的查询参数(?号后面的参数),@Query相当于@Req的res.query,@Query有两种写法:* 第一种是正常的方法写法,例如@Query(id:number,name:string),这种写法可以使用ts指定参数类型(推荐)。* 第二种是结构写法,例如@Query(){id,name},这种写法无法使用ts指定参数类型。** 访问 http://localhost:3000/findUser?id=1&name=user-1* 结果为: {"id":1,"name":"user-1"}*/@Get('/findUser')findUser(@Query() { id, name }): object {return data.filter((item) => item.id == id && item.name.indexOf(name) > -1,)[0];}/**** @Body可以获取以x-www-form-urlencoded和raw格式提交的数据*/@Post('/addUser')addUser(@Body() body): object {/*** 假设使用Postman以raw格式提交的数据内容为{"id":1}*/console.log(body); //{id:1}return body;}/*** @Param可以获取请求URL中的参数,一般用于获取动态参数,* 例如访问localhost:3000/1,下面例子中id的值为1*/@Delete(':id')delUser(@Param() { id }): string {console.log(id); //1return '删除成功';}/*** @Headers 用于获取请求头对象*/@Get('/getHeader')getHeader(@Headers() header): object {const obj = {'user-agent': 'PostmanRuntime/7.26.3',accept: '*/*','postman-token': '1e4c5aa7-918c-4363-bc13-bbfcce27565e',host: 'localhost:3000','accept-encoding': 'gzip, deflate, br',connection: 'keep-alive',};return header; // 结果为obj的内容}/*** @Header装饰器用于设置响应头信息。* @Ip装饰器用于获取请求ip。*/@Get('/getIp')@Header('Cache-Control', 'none')getIp(@Ip() ip): string {return '请求ip为:' + ip; //请求ip为:::1}/*** @Session用于获取请求Session信息*/@Get('/getSession')getSession(@Session() session) {return 'session:' + session;}/*** @HttpCode装饰器用于设置响应状态码,如不显示设置默认为200,* 当访问localhost:3000/setResCode时状态码为204 No Content*/@Post('/setResCode')@HttpCode(204)setResCode(): string {return '响应成功';}/***@Redirect装饰器用于路由转发*/@Get('/redirect')@Redirect('http://localhost:3000/findAll', 200)redirect() {return '转发成功';}/*** @Request和@Req装饰器用于设置请求对象,@Req是@Request的简写,它们的作用都是一样的,* 通过请求对象可以获取到query、param、body、ip、headers、host、hosts等参数,* 像@Query、@Param、@Body、@Ip等等这些装饰器都是对请求对象进一步封装。*/@Get('/findAll')findAll(@Req() req): Request {/*** 假设访问localhost:3000/findAll?name=zxp*/console.log('query:', req.query); //query: { name: 'zxp' }console.log('params:', req.params);console.log('body:', req.body);console.log('headers:', req.headers);console.log('ip:', req.ip); //ip: ::1console.log('host:', req.host); //host: localhostreturn req;}/*** @Response和@Res装饰器用于设置响应对象,@Res装饰器是@Response的简写,它们的作用是一样的* 通过响应对象你可以设置响应状态码、响应格式等等。* res.status(HttpStatus.OK) 用于设置响应状态码为200,* json()用于将数据转为json格式*/@Get('/findList')findList(@Res() res) {return res.status(HttpStatus.OK).json({ name: 'zxp', id: 1 });}/*** @Bind装饰器的作用是将包装的装饰器绑定到路由方法的参数,这样可以不用在路由方法中使用装饰器* 而获得同样的功能。*/@Bind(Req(), Query())bind(req, query) {console.log('请求对象:', req);console.log('请求查询参数对象:', query);}}
