NestJS02-Controllers(上)

674 阅读6分钟

Controllers

Controllers主要是用来处理客户端的请求Request和返回Response的。

路由

实际试一下Controllers的路由功能。先通过上一篇文章的方法新建一个新的工程,然后用命令行工具进到工程根目录,执行下面的命令。创建一个Cats模块。

# -d干燥模式看下是否是自己想创建的东西,执行完后显示以下内容,但是不会真的创建文件
# CREATE src/cats/cats.module.ts (81 bytes)
# UPDATE src/app.module.ts (308 bytes)
nest g module cats -d

# 确认没问题后,去掉干燥模式
nest g module cats

# 干燥模式确认Controller
# CREATE src/cats/cats.controller.spec.ts (478 bytes)
# CREATE src/cats/cats.controller.ts (97 bytes)
# UPDATE src/cats/cats.module.ts (166 bytes)
nest g co cats -d

# 会创建测试文件(spec.ts),这里不需要,所以去掉测试创建
nest g co cats --no-spec

查看工程目录,生成2个文件

routing.jpg

打开cats.controller.ts文件,修改里面的代码

import { Controller ,Get } from '@nestjs/common';

/**
 * @Controller装饰器,这里的参数cats就等于给这个路由加了一个前缀,
 * 在这个实例里面请求的路径是 /cats
 */ 
@Controller('cats')
export class CatsController {
  @Get()
  findAll(): string {
    return 'This action returns all cats';
  }
}

@Get装饰器,用来装饰方法findAll来告诉NestJS要通过Get请求来访问这个方法。也可以在装饰器里面传入参数,比如@Get('info'),那么访问地址就会变成\cats\info,通过上面的例子浏览器会返回一串字符串。

cats.jpg

  • Nest使用两种不同选项来操纵响应的概念: 标准 (推荐) | 使用此内置方法,当请求处理程序返回JavaScript对象或数组时,它将自动序列化为JSON。然而,当它返回JavaScript基元类型(例如,“string”、“number”、“boolean”)时,Nest将只发送值,而不尝试对其进行序列化。这使得响应处理变得简单:只返回值,Nest处理其余的值。此外,默认情况下,响应的状态代码始终为200,除了使用201的POST请求。我们可以通过在处理程序级别添加“@HttpCode(…)”装饰器来轻松地更改此行为(请参见状态代码)。 | | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 特定库 | 我们可以使用库特定的(例如,Express)响应对象,可以使用方法处理程序签名中的“@Res()”修饰符(例如,“findAll(@Res)response)”)注入。通过这种方法,您可以使用该对象公开的本机响应处理方法。例如,使用Express,您可以使用类似“response.status(200).send()”的代码构造响应。|
注意: Nest检测处理程序何时使用@Res()@Next(),表示您选择了库特定的选项。如果同时使用两种方法,则该单一路线的标准方法将自动禁用,不再按预期工作。要同时使用这两种方法(例如,通过注入响应对象以仅设置cookies/header,但仍将其余部分留给框架),必须在@Res({passthrough:true})修饰符中将passthrough选项设置为true

请求对象

很多情况下,处理请求需要获得请求中的参数,一般使用@req来获取请求的内容

import { Controller ,Get, Req, Bind } from '@nestjs/common';

@Controller('cats')
export class CatsController {

  /** 请求对象 */
  // 请求后返回  This action returns all cats/cats/request1
  @Get('request1')
  findAll_req1(@Req() request: Request): string {
    return 'This action returns all cats'+ request.url;
  }

  // 请求后返回  This action returns all cats/cats/request1
  @Get('request2')
  @Bind(Req())
  findAll_req2(request): string {
    return 'This action returns all cats'+ request.url;
  }
}

@req()返回的是请求头的全部内容,通常情况下不要获取这么大的一个对象,可以使用@Body @Query来去的Request里面具体的对象

装饰器实际取得内容(默认express)
@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

Resources

以上我们都是用的@Get装饰器来处理Get请求,我们还可以通过@Post来处理post请求,可以通过Postman来发出Post请求下面接口

import { Controller ,Get, Req, Bind, Post } from '@nestjs/common';

@Controller('cats')
export class CatsController {

  /** Resources */
  @Post()
  create(): string {
    return 'This action adds a new cat';
  }
}

Nest还提供了@Get()@Post()@Put()@Delete()@Patch()@Options(),@Head()@All()修饰器。

路由通配符

*通佩服可以匹配任何字段。abcdab_cdabecd这些路径名称都会被匹配。通配符还可以使用正则表达式。

import { Controller ,Get, Req, Bind, Post } from '@nestjs/common';

@Controller('cats')
export class CatsController {
  /** 路由通配符 */
  @Get('ab*cd')
  findAll_wildcards() {
    return 'This route uses a wildcard';
  }
}

请求结果

wildcard.jpg

状态码

一般情况下,返回的状态码是200Post返回的是201,可以自定义状态码。

import { Controller ,Get, Req, Bind, Post, HttpCode } from '@nestjs/common';

@Controller('cats')
export class CatsController {

  /** 状态码 */
  // 返回状态码 204
  @Post()
  @HttpCode(204)
  create_status_code() {
    return 'This action adds a new cat';
  }
}

以上的方式是静态的,也可以通过@Res()动态的设定状态码,或者通过抛出内置异常等来设定状态码

返回Header头

可以通过@Header自定义返回的Header

import { Controller ,Get, Req, Bind, Post, HttpCode, Header } from '@nestjs/common';

@Controller('cats')
export class CatsController {

  /** 返回头 */
  @Post()
  // 指定返回头中的内容
  @Header('Cache-Control', 'none')
  create_header() {
    return 'This action adds a new cat';
  }
}

通过postman确认

header.jpg

重定向

要将响应重定向到特定的URL,可以使用@redirect()装饰器或库特定的响应对象(并直接调用res.redirect())。 @Redirect()接受一个必需的url参数和一个可选的statusCode参数。如果省略,statusCode默认为302

import { Controller ,Get, Req, Bind, Post, HttpCode, Header,Redirect } from '@nestjs/common';

@Controller('cats')
export class CatsController {

  /** 重定向 */
  // 访问 http://localhost:3000/cats/redirect 跳转到 'nestjs.com'
  @Get('redirect')
  @Redirect('https://nestjs.com', 301)
  // 任意方法名 
  redirect(){}
}

有时您可能需要动态确定HTTP状态代码或重定向URL。为此,请从路由处理程序方法返回一个具有以下形状的对象

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

例子:

import { Controller ,Get, Req, Bind, Post, HttpCode, Header,Redirect, Query } from '@nestjs/common';

@Controller('cats')
export class CatsController {
  
  /*
   * 访问 http://localhost:3000/cats/docs?version=5 跳转到 https://docs.nestjs.com/v5/'
   * 访问 http://localhost:3000/cats/docs 跳转到 https://docs.nestjs.com'
   */
  @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的cat),带有静态路径的路由将无法工作。为了用参数定义路由,我们可以在路由的路径中添加路由参数标记,以捕获请求URL中该位置的动态值。下面@Get()装饰器示例中的路由参数标记演示了这种用法。可以使用@Param()修饰符访问以这种方式声明的路由参数,该修饰符应添加到方法签名中。

import { Controller ,Get, Req, Bind, Post, HttpCode, Header,Redirect, Query, Param } from '@nestjs/common';

@Controller('cats')
export class CatsController {

  /** 路由参数 */
  @Get('param1/:id')
  findOne1(@Param() params): string {
    console.log(params.id);
    return `This action returns a #${params.id} cat`;
  }

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

@Param()用于修饰方法参数(上例中的params),并使路由参数作为该修饰方法参数在方法体内的可用。如上面的代码所示,我们可以通过引用params.id来访问id参数。您还可以将特定的参数令牌传递给decorator,然后在方法体中直接通过名称引用路由参数。

import { Controller ,Get, Req, Bind, Post, HttpCode, Header,Redirect, Query, Param } from '@nestjs/common';

@Controller('cats')
export class CatsController {
  /** 路由参数 */
  @Get('param1/:id')
  findOne1(@Param() params): string {
    console.log(params.id);
    return `This action returns a #${params.id} cat`;
  }

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

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

  @Get('param4/:id')
  @Bind(Param('id'))
  findOne4(id) {
    return `This action returns a #${id} cat`;
  }
}

代码链接地址

代码