返回顶部
首页 > 资讯 > 前端开发 > JavaScript >Node.js控制器Controller使用教程
  • 818
分享到

Node.js控制器Controller使用教程

Node.js控制器ControllerNode.js控制器Node.jsController 2023-05-15 20:05:45 818人浏览 八月长安
摘要

目录Controller 控制器路由请求对象资源路由通配符状态代码头信息重定向路由参数子域路由范畴异步性请求的有效载荷处理错误完整例子开始运行库的特定方法Controller 控制器

Controller 控制器

控制器负责处理传入的请求并向客户返回响应。

一个控制器的目的是接收应用程序的特定请求。路由机制控制哪个控制器接收哪些请求。通常,每个控制器有一个以上的路由,不同的路由可以执行不同的动作。

为了创建一个基本的控制器,我们使用类和装饰器。装饰器将类与所需的元数据联系起来,并使 Nest 能够创建一个路由图(将请求绑定到相应的控制器)。

为了快速创建一个内置验证的 CRUD 控制器,你可以使用 CLI 的 CRUD 生成器:nest g resource [name]

路由

在下面的例子中,我们将使用@Controller()装饰器,这是定义一个基本控制器所需要的。我们将指定一个可选的路由路径前缀为cats。在@Controller()装饰器中使用路径前缀,可以让我们轻松地将一组相关的路由分组,并尽量减少重复的代码。例如,我们可以选择将一组管理与客户实体互动的路由归入路由/customers。在这种情况下,我们可以在@Controller()装饰器中指定路径前缀customers,这样我们就不必为文件中的每个路由重复这部分的路径。

import { Controller, Get } from "@nestjs/common";
@Controller("cats")
export class CatsController {
  @Get()
  findAll(): string {
    return "This action returns all cats";
  }
}

要使用 CLI 创建一个控制器,只需执行$ nest g controller cats命令。

findAll()方法之前的@Get() Http 请求方法装饰器,告诉 Nest 为 HTTP 请求的特定端点创建一个处理程序。端点与 HTTP 请求方法(本例中为 GET)和路由路径相对应。

什么是路由路径?处理程序的路径是通过连接控制器声明@Controller('cats')中的cats,以及方法装饰器@Get()中指定的任何路径来确定的。由于我们已经为每个路由(cats)声明了一个前缀,并且没有在装饰器@Get()中添加任何路径信息,Nest 就会将GET /cats请求映射到findAll()的Get方法上来。

如前所述,路径包括@Controller()路径前缀和请求方法findAll()装饰器@Get()中配置的路径。例如,@Controller('customers')的路径前缀与装饰器@Get('profile')相结合,将产生一个GET /customers/profile这样的路由映射请求。

在我们上面的例子中,当向该端点发出 GET 请求时,Nest 将该请求路由到我们用户定义的 findAll()方法。注意,我们在这里选择的方法名称是完全任意的。显然,我们必须声明一个方法来绑定路由,但 Nest 并不重视所选择的方法名称的任何意义。

这个方法将返回一个 200 状态代码和相关的响应,在这种情况下,它只是一个字符串。为什么会发生这种情况?为了解释,我们首先要介绍一个概念,即 Nest 采用了两种不同的选项来操作响应。

选项描述
Standard (recommended)使用这种内置方法,当请求处理程序返回一个 javascript 对象或数组时,它将自动被序列化为 JSON。然而,当它返回一个 JavaScript 原始类型(例如,字符串、数字、布尔值)时,Nest 将只发送值,而不尝试对其进行序列化。这使得响应处理变得简单:只需返回值,Nest 就会处理其余的事情。此外,响应的状态代码默认总是 200,除了使用 201 的 POST 请求。我们可以通过在处理程序级别添加@HttpCode(…)装饰器来轻松改变这一行为(见状态代码)。
Library-specific我们可以使用库特定的(例如 Express)响应对象,它可以使用方法处理签名中的@Res()装饰器注入(例如 findAll(@Res() response))。通过这种方法,你有能力使用该对象所暴露的本地响应处理方法。例如,在 Express 中,你可以使用 response.status(200).send()这样的代码来构造响应。

警告:

NEST 会检测处理程序是否使用@Res()或@Next(),表明你选择了库的特定选项。如果同时使用这两种方法,标准方法将自动禁用于该单一路由,并不再按预期工作。要同时使用这两种方法(例如,通过注入响应对象只设置 cookie/头文件,但仍将其余部分留给框架),你必须在@Res({ passthrough: true })装饰器中将 passthrough 选项设置为 true。

请求对象

处理程序经常需要访问客户端的请求细节。Nest 提供了对底层平台(默认为 Express)的请求对象的访问。我们可以通过在处理程序的签名中添加@Req()装饰器来指示 Nest 注入请求对象来访问它。

import { Controller, Get, Req } from "@nestjs/common";
import { Request } from "express";
@Controller("cats")
export class CatsController {
  @Get()
  findAll(@Req() request: Request): string {
    return "This action returns all cats";
  }
}

为了利用表达式类型的优势(如上面的 request: Request 参数的例子),请安装@types/express 包。

请求对象代表了 HTTP 请求,并有请求查询字符串、参数、HTTP 头和正文的属性(在此阅读更多内容)。在大多数情况下,没有必要手动抓取这些属性。我们可以使用专门的装饰器来代替,比如@Body()@Query(),这些装饰器开箱即用。下面是一个所提供的装饰器的列表,以及它们所代表的普通平台特定对象。

装饰器特定对象
@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 平台(例如ExpressFastify)的类型兼容,Nest 提供了@Res()@Response()装饰器。@Res()@Response() 的简单别名。两者都直接暴露了底层的本地平台响应对象接口。当使用它们时,你也应该导入底层库的类型(例如,@types/express)以充分利用。请注意,当你在方法处理程序中注入@Res()@Response()时,你将 Nest 放入该处理程序的库特定模式中,并且你将负责管理响应。当这样做时,你必须通过调用响应对象(如 res.json(...)res.send(...))来发出某种响应,否则 HTTP 服务器会挂起。

如何定义自己的装饰器,请学习这个章节

资源

早些时候,我们定义了一个方法来获取cats的资源(GET 路由)。我们通常也想提供一个创建新记录的方法。为此,让我们创建一个 POST 方法。

import { Controller, Get, Post } from "@nestjs/common";
@Controller("cats")
export class CatsController {
  @Post()
  create(): string {
    return "This action adds a new cat";
  }
  @Get()
  findAll(): string {
    return "This action returns all cats";
  }
}

就是这么简单。Nest 为所有的标准 HTTP 方法提供装饰器。 @Get(), @Post(), @Put(), @Delete(), @Patch(), @Options(), 和 @Head()。此外,@All()定义了一个可以处理所有这些方法的端点。

路由通配符

基于路由的模式也被支持。例如,*被用作通配符,将匹配任何字符的组合。

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

ab*cd 路由路径将匹配 abcd、ab_cd、abecd,等等。字符"?“、”+“、”*“和”()"可以在路径中使用,它们是对应于正则表达式的子集。连字符(-)和点(.)可以通过基于字符串的路径进行字面解释。

状态代码

如前所述,响应状态代码默认总是 200,除了 POST 请求是 201。我们可以通过在处理程序级别添加@HttpCode(...)装饰器来轻松改变这一行为。

@Post()
@HttpCode(204)
create() {
  return 'This action adds a new cat';
}

@nestjs/common包导入HttpCode

通常,你的状态代码不是静态的,而是取决于各种因素。在这种情况下,你可以使用一个库特定的响应(使用@Res()注入)对象(或者,在出现错误时,抛出一个异常)。

头信息

要指定一个自定义的响应头,你可以使用@Header()装饰器或一个库特定的响应对象(并直接调用res.header())。

@Post()
@Header('Cache-Control', 'none')
create() {
  return 'This action adds a new cat';
}

@nestjs/common包导入Header

重定向

要将一个响应重定向到一个特定的 URL,你可以使用@Redirect()装饰器或一个库特定的响应对象(并直接调用res.redirect())。

@Redirect()需要两个参数,urlstatusCode,都是可选的。如果省略的话,statusCode的默认值是302

@Get()
@Redirect('https://nestjs.com', 301)

有时你可能想动态地确定 HTTP 状态代码或重定向 URL。通过从路由处理方法中返回一个对象来做到这一点,类似如下。

{
  "url": string,
  "statusCode": number
}

返回的值将覆盖传递给@Redirect()装饰器的任何参数。比如说。

@Get('docs')
@Redirect('https://docs.nestjs.com', 302)
getDocs(@Query('version') version) {
  if (version && version === '5') {
    return { url: 'https://docs.nestjs.com/v5/' };
  }
}

路由参数

当你需要接受动态数据作为请求的一部分时,带有静态路径的路由将无法工作(例如,GET /cats/1 以获得 id 为 1 的猫)。为了定义带参数的路由,我们可以在路由的路径中添加路由参数令牌,以捕获请求 URL 中该位置的动态值。下面@Get()装饰器例子中的路由参数令牌展示了这种用法。以这种方式声明的路由参数可以使用@Param()装饰器进行访问,它应该被添加到方法签名中。

@Get(':id')
findOne(@Param() params): string {
  console.log(params.id);
  return `This action returns a #${params.id} cat`;
}

@Param()被用来装饰一个方法参数(上面例子中的params),并使路由参数作为该方法主体中被装饰的方法参数的属性可用。正如上面的代码所见,我们可以通过引用params.id来访问id参数。你也可以向装饰器传递一个特定的参数标记,然后在方法主体中直接引用路由参数的名称。

@nestjs/common包导入Param

@Get(':id')
findOne(@Param('id') id: string): string {
  return `This action returns a #${id} cat`;
}

子域路由

@Controller装饰器可以接受一个host选项,要求传入的请求的 HTTP 主机与某些特定的值相匹配。

@Controller({ host: "admin.example.com" })
export class AdminController {
  @Get()
  index(): string {
    return "Admin page";
  }
}

由于 Fastify 缺乏对嵌套路由器的支持,当使用子域路由时,应该使用(默认)Express 适配器来代替

与路由路径类似,hosts选项可以使用令牌来捕获主机名称中该位置的动态值。下面@Controller()装饰器例子中的主机参数令牌展示了这种用法。以这种方式声明的主机参数可以使用@HostParam()装饰器进行访问,它应该被添加到方法签名中。

@Controller({ host: ":account.example.com" })
export class AccountController {
  @Get()
  getInfo(@HostParam("account") account: string) {
    return account;
  }
}

范畴

对于来自不同编程语言背景的人来说,要知道在 Nest 中,几乎所有的东西都是在传入的请求中共享的,这可能是意想不到的。我们有一个到数据库的连接池,有全局状态的单体服务,等等。请记住,node.js 并不遵循请求/响应的多线程无状态模型,其中每个请求都由一个单独的线程来处理。因此,使用单体实例对我们的应用程序是完全安全的。

但是,在极端情况下,基于请求的控制器生存周祁可能是所需的行为(However, there are edge-cases when request-based lifetime of the controller may be the desired behavior),例如 GraphQL 应用程序中的每个请求缓存,请求跟踪或多租户。在这里了解如何控制作用域。

异步性

我们热爱现代 JavaScript,我们知道数据提取大多是异步的。这就是为什么 Nest 支持并能很好地使用异步函数。

学习async / await请点击这里

每个异步函数都必须返回一个 Promise。这意味着你可以返回一个延迟值,Nest 将能够自己解决。让我们来看看这个例子。

@Get()
async findAll(): Promise<any[]> {
  return [];
}

上述代码是完全有效的。此外,Nest 路由处理程序通过能够返回 RxJS 可观察流而变得更加强大。Nest 将自动订阅下面的源并获取最后一个发出的值(一旦流完成)–( Nest will automatically subscribe to the source underneath and take the last emitted value (once the stream is completed))

@Get()
findAll(): Observable<any[]> {
  return of([]);
}

上述两种方法都有效,你可以使用任何符合你要求的方法。

请求的有效载荷

我们之前的 POST 路由处理器的例子没有接受任何客户端参数。让我们通过在这里添加@Body()装饰器来解决这个问题。

但首先(如果你使用 typescript),我们需要确定 DTO(数据传输对象)模式。DTO 是一个定义了数据如何在网络上发送的对象。我们可以通过使用 TypeScript 接口,或通过简单的类来确定 DTO 模式。有趣的是,我们在这里推荐使用类。为什么呢?类是 JavaScript es6 标准的一部分,因此它们在编译后的 JavaScript 中被保留为真实的实体。另一方面,由于 TypeScript 接口在转译过程中被移除,Nest 不能在运行时引用它们。这一点很重要,因为像管道这样的功能在运行时可以访问变量的元类型,从而实现更多的可能性。

我们来创建CreateCatDto类。

export class CreateCatDto {
  name: string;
  age: number;
  breed: string;
}

它只有三个基本属性。此后我们可以在CatsController中使用新创建的DTO

我们的 Validation Pipe 可以过滤掉那些不应该被方法处理程序接收的属性。在这种情况下,我们可以将可接受的属性列入白名单,任何不包括在白名单中的属性都会自动从结果对象中剥离。在CreateCatDto的例子中,我们的白名单是名称、年龄和品种属性。在这里了解更多。

处理错误

这里有一个关于处理错误的单独章节(即,与异常一起工作)。

完整例子

下面是一个例子,利用几个可用的装饰器来创建一个基本的控制器。这个控制器暴露了一些方法来访问和操作内部数据。

import {
  Controller,
  Get,
  Query,
  Post,
  Body,
  Put,
  Param,
  Delete,
} from "@nestjs/common";
import { CreateCatDto, UpdateCatDto, ListAllEntities } from "./dto";
@Controller("cats")
export class CatsController {
  @Post()
  create(@Body() createCatDto: CreateCatDto) {
    return "This action adds a new cat";
  }
  @Get()
  findAll(@Query() query: ListAllEntities) {
    return `This action returns all cats (limit: ${query.limit} items)`;
  }
  @Get(":id")
  findOne(@Param("id") id: string) {
    return `This action returns a #${id} cat`;
  }
  @Put(":id")
  update(@Param("id") id: string, @Body() updateCatDto: UpdateCatDto) {
    return `This action updates a #${id} cat`;
  }
  @Delete(":id")
  remove(@Param("id") id: string) {
    return `This action removes a #${id} cat`;
  }
}

Nest CLI 提供了一个自动生成器(示意图),自动生成所有的模板代码,以帮助我们避免做这些事情,并使开发人员的体验更加简单。在这里阅读更多关于这个功能的信息。

开始运行

随着上述控制器的完全定义,Nest 仍然不知道CatsController的存在,因此不会创建这个类的实例。

控制器总是属于一个模块,这就是为什么我们在@Module()装饰器中包含控制器数组。由于我们还没有定义任何其他模块,除了根AppModule,我们将用它来介绍CatsController

import { Module } from "@nestjs/common";
import { CatsController } from "./cats/cats.controller";
@Module({
  controllers: [CatsController],
})
export class AppModule {}

我们使用@Module()装饰器将元数据附加到模块类,Nest 现在可以很容易地反映出哪些控制器必须被安装。

库的特定方法

到目前为止,我们已经讨论了操作响应的 Nest 标准方式。操作响应的第二种方式是使用库特定的响应对象。为了注入一个特定的响应对象,我们需要使用 @Res() 装饰器。为了显示差异,让我们把CatsController重写成以下内容。

import { Controller, Get, Post, Res, HttpStatus } from "@nestjs/common";
import { Response } from "express";
@Controller("cats")
export class CatsController {
  @Post()
  create(@Res() res: Response) {
    res.status(HttpStatus.CREATED).send();
  }
  @Get()
  findAll(@Res() res: Response) {
    res.status(HttpStatus.OK).json([]);
  }
}

虽然这种方法是可行的,而且事实上通过提供对响应对象的完全控制,在某些方面确实有更大的灵活性(头文件的操作、库的特定功能等等),但是应该谨慎使用。一般来说,这种方法不那么明确,而且确实有一些缺点。主要的缺点是,你的代码变得依赖于平台(因为底层库在响应对象上可能有不同的 api),而且更难测试(你必须模拟响应对象,等等)。

另外,在上面的例子中,你失去了与依赖 Nest 标准响应处理的 Nest 功能的兼容性,如拦截器和@HttpCode() / @Header() 装饰器。为了解决这个问题,你可以将 passthrough 选项设置为 true,如下所示。

@Get()
findAll(@Res({ passthrough: true }) res: Response) {
  res.status(HttpStatus.OK);
  return [];
}

现在,你可以与本地响应对象进行交互(例如,根据某些条件设置 cookies 或头信息),但把其余的事情留给框架。

到此这篇关于node.js控制器Controller使用教程的文章就介绍到这了,更多相关Node.js Controller内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Node.js控制器Controller使用教程

本文链接: https://lsjlt.com/news/209447.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Node.js控制器Controller使用教程
    目录Controller 控制器路由请求对象资源路由通配符状态代码头信息重定向路由参数子域路由范畴异步性请求的有效载荷处理错误完整例子开始运行库的特定方法Controller 控制器...
    99+
    2023-05-15
    Node.js控制器Controller Node.js控制器 Node.js Controller
  • Node.js控制器Controller如何使用
    本篇内容介绍了“Node.js控制器Controller如何使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Controller 控制器控...
    99+
    2023-07-06
  • SpringMVC编程使用Controller接口实现控制器实例代码
    Controller简介Controller控制器,是MVC中的部分C,为什么是部分呢?因为此处的控制器主要负责功能处理部分:收集、验证请求参数并绑定到命令对象;将命令对象交给业务对象,由业务对象处理并返回模型数据;返回ModelAndVi...
    99+
    2023-05-30
    springmvc controller 控制器
  • ASP.NETCoreMVC中的控制器(Controller)介绍
    操作(action)和操作结果(action result)是 ASP.NET MVC 构建应用程序的一个基础部分。在 ASP.NET MVC 中,控制器用于定义和聚合一组操作。操作...
    99+
    2024-04-02
  • 在Spring Boot中使用Controller实现控制页面
    本篇文章给大家分享的是有关在Spring Boot中使用Controller实现控制页面,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。一.项目实例项目结构项目代码1).Acti...
    99+
    2023-05-31
    springboot controller roller
  • node.js中 stream使用教程
    这些日子跑去学了一下OC,但是还没有学成。离转行的时间还有很长,顺便回顾一下node的知识。 每种语言来来去去的人很多,但我就离不开node。我并不是使用它开发,只是使用js相对多一些,因此还是研究node...
    99+
    2022-06-04
    教程 node js
  • 云服务器怎么远程控制设备使用教程
    远程控制设备使用是指使用网络远程控制服务器上的设备,以实现对设备的操作或管理。以下是一些远程控制设备使用的示例: 使用Agent程序远程管理设备。 Agent是一个计算机程序,它可以连接到服务器,并在客户端上执行各种远程控制操作。例如...
    99+
    2023-10-26
    控制设备 服务器 教程
  • 解决ThinkPHP6 控制器不存在:app\controller\Index
    报错原因:控制器的Index类没有找到 解决方法: (1)安装thinkphp6多应用模式扩展think-multi-ap 命令行:composer require topthink/think-multi-app (2) config/...
    99+
    2023-09-07
    php
  • node.js中cluster的使用教程
    本文主要给大家介绍了关于node.js中cluster使用的相关教程,分享出来供大家参考学习,下面来看看详细的介绍: 一、使用NODE中cluster利用多核CPU var cluster = requ...
    99+
    2022-06-04
    教程 node js
  • 教你如何使用node.js制作代理服务器
    下面代码实现的功能是这样的: 首先创建一个HTTP服务器,当服务器接收到客户端的请求后,向"www.taobao.com"网站请求数据,当从该网站接受到的响应数据后,将响应数据发送给客户端. var ht...
    99+
    2022-06-04
    教你 代理服务器 如何使用
  • 第四章 SpringMVC--Controller接口控制器详解(3)
    11、AbstractWizardFormController向导控制器类提供了多步骤(向导)表单的支持(如完善个人资料时分步骤填写基本信息、工作信息、学校信息等)假设现在做一个完善个人信息的功能,分三个页面展示:页面1完善基本信息;页面2...
    99+
    2023-06-03
  • tp6.1多应用控制器不存在:app\应用名\controller\应用名
    软件版本 thinkphp:6.1 apache:2.4(错误和服务器没关系) 错误描述 单域名访问操作多应用访问正常;但新增了域名(域名绑定应用[官方文档])配置config/app.php的dom...
    99+
    2023-09-11
    php 开发语言 thinkphp6
  • Spring MVC如何实现接口Controller定义控制器
    目录实现接口Controller定义控制器方法一:实现接口Controller定义控制器方法二:使用注解@Controller定义控制器详谈Controller(控制器)一、cont...
    99+
    2024-04-02
  • 详解Node.js串行化流程控制
    串行任务:需要一个接着一个坐的任务叫做串行任务。 可以使用回调的方式让几个异步任务按顺序执行,但如果任务过多,必须组织一下,否则过多的回调嵌套会把代码搞得很乱。 为了用串行化流程控制让几个异步任务按顺序执行...
    99+
    2022-06-04
    详解 流程 串行化
  • 使用npm发布Node.JS程序包教程
    npm是Node.JS的程序包管理器。进行Node.JS开发时,经常使用它安装/卸载程序包。实际上,发布程序包的工作也是由它来完成的。 配置package.json 要打包程序,首先要配好各项设置,这些设置...
    99+
    2022-06-04
    程序包 教程 npm
  • node.js中如何使用async异步控制工具
    node.js中如何使用async异步控制工具,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。这两个操作中,第一个异步的程序我们可能会写成这...
    99+
    2024-04-02
  • Node.js的npm包管理器基础使用教程
    配置 npm set npm set init-author-name 'Your name' npm set init-author-email 'Your email' npm set init...
    99+
    2022-06-04
    管理器 基础 教程
  • Win7使用注册表禁用控制面板图文教程
    通常情况下使用电脑久了对于一些系统的设置及使用都比较熟悉,我们都不希望别人在使用自己电脑的时候乱改系统设置,而一些小白在修改系统设置的方法一般是通过控制面板来修改的,那么我们有没有什么方法将win7系统的控制面板禁止掉,...
    99+
    2023-06-07
    Win7 注册表 禁用控制面板 禁用 控制面板 图文
  • WindowsServer2019安装域控制器(图文教程)
    (1)打开服务器管理器,添加角色和功能。 (2)出现“添加角色和功能”界面,下一步  。 (3)根据提示操作,下一步。 (4)选择添加AD域...
    99+
    2024-04-02
  • Minio控制台详细教程
    前言 此文讲解Minio控制台详细教程,可能会涉及到有些知识大家可能不懂情况。 需要知道Minio兼容的是AMS S3对象存储服务。需要知道AMS S3对象存储服务是什么,里面涉及的到配置如何去配等等...
    99+
    2023-09-04
    java
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作