前言

控制器主要是用来处理客户端传入的请求并向客户端返回响应。

它一般是用来做路由导航的,内部路由机制控制哪个控制器接收哪些请求。

路由

为了创建基本控制器,我们需要使用@Controller装饰器,装饰器将类与所需元数据关联起来,并使Nest能够创建路由映射。

我们使用nest-cli快速创建一个REST API风格的完整CURD代码。

nest g resource nanjiu

在生成的nanjiu文件夹下,我们可以看到有nanjiu.controller.ts文件,代码如下:

// nanjiu.controller.ts
import { Controller, Get, Post, Body, Patch, Param, Delete, Query } from '@nestjs/common';
import { NanjiuService } from './nanjiu.service';
import { CreateNanjiuDto } from './dto/create-nanjiu.dto';
import { UpdateNanjiuDto } from './dto/update-nanjiu.dto'; @Controller('nanjiu')
export class NanjiuController {
constructor(private readonly nanjiuService: NanjiuService) {} @Post()
create(@Body() createNanjiuDto: CreateNanjiuDto) {
return this.nanjiuService.create(createNanjiuDto);
} @Get()
findAll(@Param() params, @Query() query) {
console.log('find', query)
return this.nanjiuService.findAll();
} @Get(':id')
findOne(@Param('id') id: string) {
return this.nanjiuService.findOne(+id);
} @Patch(':id')
update(@Param('id') id: string, @Body() updateNanjiuDto: UpdateNanjiuDto) {
return this.nanjiuService.update(+id, updateNanjiuDto);
} @Delete(':id')
remove(@Param('id') id: string) {
return this.nanjiuService.remove(+id);
}
}

@controller装饰器中传入了nanjiu参数,表示指定路由前缀nanjiu,在@controller装饰器中使用路由前缀,可以让我们很轻松地将一组相关路由放在一起集中管理。

比如当我们通过get方式请求/nanjiu这个路由时,它应该会走到@get装饰器修饰的findAll方法内

可以使用ApiFox工具进行接口测试:

从上图中可以看到我此时的请求路径是http://localhost:3000/apinanjiu,是不是很好奇为了什么多了一层/api,这是因为我加了一层全局路由前缀

// main.ts
app.setGlobalPrefix('api'); // 全局路由前缀

这里我们还可以看到状态码为200,并且能够看到findAll的返回值,就说明此时的请求是正常的,但右边还有个error提示返回数据结构与接口定义不一致。

这是因为这里我们只是简单地返回了一个字符串,并不符合JSON格式

Nest中,有两种选项来处理响应值:

  • 标准模式:使用此内置方法,当请求处理程序返回 JavaScript 对象或数组时,它将自动序列化为 JSON。然而,当它返回 JavaScript 基本类型(例如,stringnumberboolean)时,Nest 将仅发送该值,而不尝试对其进行序列化。这使得响应处理变得简单:只需返回值,Nest 就会处理其余的事情。

    此外,默认情况下,响应的状态代码始终为 200,除了使用 201 的 POST 请求。我们可以通过@HttpCode(...)在处理程序级别添加装饰器来轻松更改此行为

  • 特定库模式:我们可以使用特定于库的(例如,Express)响应对象@Res(),可以使用方法处理程序签名中的装饰器注入该对象(例如, findAll(@Res() response))。通过这种方法,您可以使用该对象公开的本机响应处理方法。例如,使用 Express,可以使用response.status(200).send().

路由通配符

Nest还支持基于模式的路由,比如,使用通配符

@Get('ab*cd')
findAll() {
return 'This route uses a wildcard';
}

路由'ab*cd'路径将匹配abcdab_cdabecd等。字符?+*()可以在路由路径中使用,并且是其正则表达式对应项的子集。连字符 ( -) 和点 ( .) 按字面意思解释为基于字符串的路径。

请求对象

作为后端项目,访问客户端请求的详细信息也非常重要,从上面生成的代码中我们可以看到@Body@Param@Query等装饰器,没错,在大多数时候我们并不需要手动获取请求对象(查询字符串、参数、请求头、正文等),直接通过这些开箱即用的装饰器就能快速获取。

比如我们在findAll内加上日志

// nanjiu.controller.ts
@Get()
findAll(@Param() params, @Query() query) {
console.log('find', params, query) // 日志
return this.nanjiuService.findAll();
}

然后在请求时带上一些参数:

此时我们再来看看后端打印的日志:

这里就能看到前端请求传过来的Query参数为city: shanghai

这些开箱即用的装饰器有以下这些:

@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

HTTP请求方法

从上面生成的代码中的,我们可以发现除了@Get请求方法装饰器外还有一些其它的,事实上,Nest为所有标准 HTTP 方法提供了装饰器:@Get()@Post()@Put()@Delete()@Patch()@Options()@Head()

一般大家常用的都是get请求与post请求吧,好像很少看到其它类型的请求

获取get请求参数

这里可以使用@Request装饰器与@Query装饰器,与express完全一致

上面已经演示了通过@Query获取,那就在通过@Request再演示一遍

// nanjiu.controller.ts
@Get()
findAll(@Request() req, @Query() query) {
console.log('find', req.query, query)
return this.nanjiuService.findAll();
}

通过req.queryQuery获取的是一致的,所以使用@Query装饰器获取get类型的请求参数会更方便一些,如果你还想获取更多关于请求的参数可以使用@Request装饰器。

获取post请求参数

express一样,可以使用@Request装饰器与Body装饰器

// nanjiu.controller.ts
@Post()
create(@Body() createNanjiuDto: CreateNanjiuDto) {
console.log('body', createNanjiuDto)
return this.nanjiuService.create(createNanjiuDto);
}

查看日志

动态路由

当需要接受动态数据作为请求的一部分(例如,GET /nanjiu/1获取带有 id 为 1nanjiu)时,具有静态路径的路由将不起作用。为了定义带参数的路由,我们可以在路由的路径中添加路由参数**标记,以捕获请求 URL 中该位置的动态值。**下面装饰器示例中的路由参数标记@Get()演示了这种用法。以这种方式声明的路由参数可以使用装饰器来访问@Param()

// nanjiu.controller.ts
@Get(':id')
findOne(@Param() params) {
console.log('params', params)
return this.nanjiuService.findOne(+params.id);
}

查看日志

状态码

从上面几个例子我们可以看到,默认情况下响应状态码都是200POST请求除外,POST默认为201Nest同样提供了HttpCode()装饰器来自定义响应状态码

// nanjiu.controller.ts
@Get()
@HttpCode(202)
findAll(@Request() req, @Query() query) {
console.log('find', req, query)
return this.nanjiuService.findAll();
}

响应头

想要自定义响应头,可以使用@Header装饰器

@Post()
@Header('Cache-Control', 'none')
create(@Body() createNanjiuDto: CreateNanjiuDto) {
console.log('body', createNanjiuDto)
return this.nanjiuService.create(createNanjiuDto);
}

【NestJS系列】核心概念:Controller控制器的更多相关文章

  1. Spark系列-核心概念

    Spark系列-初体验(数据准备篇) Spark系列-核心概念 一. Spark核心概念 Master,也就是架构图中的Cluster Manager.Spark的Master和Workder节点分别 ...

  2. ZooKeeper 系列(一)—— ZooKeeper核心概念详解

    一.Zookeeper简介 二.Zookeeper设计目标 三.核心概念         3.1 集群角色         3.2 会话         3.3 数据节点         3.4 节点 ...

  3. ZooKeeper系列(一)—— ZooKeeper 简介及核心概念

    一.Zookeeper简介 Zookeeper 是一个开源的分布式协调服务,目前由 Apache 进行维护.Zookeeper 可以用于实现分布式系统中常见的发布/订阅.负载均衡.命令服务.分布式协调 ...

  4. Storm 系列(二)—— Storm 核心概念详解

    一.Storm核心概念 1.1 Topologies(拓扑) 一个完整的 Storm 流处理程序被称为 Storm topology(拓扑).它是一个是由 Spouts 和 Bolts 通过 Stre ...

  5. 框架源码系列十:Spring AOP(AOP的核心概念回顾、Spring中AOP的用法、Spring AOP 源码学习)

    一.AOP的核心概念回顾 https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/core.html#a ...

  6. Kubernetes核心概念总结

    目录贴:Kubernetes学习系列 1.基础架构 1.1 Master Master节点上面主要由四个模块组成:APIServer.scheduler.controller manager.etcd ...

  7. 后端技术杂谈11:十分钟理解Kubernetes核心概念

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 本文转自 https://github.com/h2pl/Java-Tutorial 喜欢的 ...

  8. kubernetes核心概念

    摘抄自:  https://www.cnblogs.com/zhenyuyaodidiao/p/6500720.html 1.基础架构 1.1 Master Master节点上面主要由四个模块组成:A ...

  9. [转]k8s核心概念

    转载自 https://blog.csdn.net/real_myth/article/details/78719244 什么是kubernetes 首先,他是一个全新的基于容器技术的分布式架构领先方 ...

  10. Kubernetes 核心概念

    什么是Kubernetes? Kubernetes(k8s)是自动化容器操作的开源平台,这些操作包括部署,调度和节点集群间扩展.如果你曾经用过Docker容器技术部署容器,那么可以将Docker看成K ...

随机推荐

  1. Linux内存和磁盘管理(入门)

    关于对Linux系统的内存和磁盘的操作 内存和磁盘使用率 查看内存使用率: free.top 查看磁盘使用率: fdisk.df.du free 以KB为单位: $ free total used f ...

  2. Pandas的使用

    在数据分析工作中,Pandas 的使用频率是很高的,一方面是因为 Pandas 提供的基础数据结构 DataFrame 与 json 的契合度很高,转换起来很方便.另一方面,如果日常的数据清理工作不是 ...

  3. 21-HMR

    /* HMR:hot module replacement 热模块替换 / 模块热替换 作用:一个模块发生变化,只会重新打包这一个模块(而不是打包所有模块) 极大提升构建速度 样式文件:可以使用HMR ...

  4. springboot mybatis 动态调用oracle存储过程,通过存储过程名称,就能动态调用存储过程、java动态调用oracle存储过程

    由于在开发业务时,可能同时调用的存储过程不知道参数,但是参数从界面.或已经存储在数据库的获取,所以就不希望手动写存储过程的参数,通过简化的调用. 能不能写个动态的业务,只输入存储过程名称,自动获取存储 ...

  5. 深度学习-05(tensorflow模型保存与加载、文件读取、图像分类:手写体识别、服饰识别)

    文章目录 深度学习-05 模型保存于加载 什么是模型保存与加载 模型保存于加载API 案例1:模型保存/加载 读取数据 文件读取机制 文件读取API 案例2:CSV文件读取 图片文件读取API 案例3 ...

  6. 案例分享-full gc导致k8s pod重启

    在之前的记一次k8s pod频繁重启的优化之旅中分享过对于pod频繁重启的一些案例,最近又遇到一例,继续分享出来希望能给大家带来些许收获. 问题现象 报警群里突然显示某pod频繁重启,我随即上去查看日 ...

  7. pytest的几种执行方式

    1 pytest xxxx 2 python -m pytest xxxx python -m pytest --html=./report/rep2.html test_env_pytest_ini ...

  8. JavaFx 关键字高亮文本实现

    原文地址:JavaFx 关键字高亮文本实现 - Stars-One的杂货小窝 整蓝奏云批量下载器里的搜索功能想到的一个关键字高亮功能,借助textflow组件来实现,记录一下 本文基于TornadoF ...

  9. 2023-04-21:用go语言重写ffmpeg的metadata.c示例。

    2023-04-21:用go语言重写ffmpeg的metadata.c示例. 答案2023-04-21: 这段 Go 代码演示了如何使用 ffmpeg-go 库中的函数来读取多媒体文件元数据,包括视频 ...

  10. 2023-03-23:音视频解混合(demuxer)为PCM和YUV420P,用go语言编写。

    2023-03-23:音视频解混合(demuxer)为PCM和YUV420P,用go语言编写. 答案2023-03-23: 大体步骤如下: 1.打开媒体文件,并获取音频和视频流. 2.对于每个流,找到 ...