神光《Nest 通关秘籍》学习总结 您所在的位置:网站首页 mysql结课心得1000字 神光《Nest 通关秘籍》学习总结

神光《Nest 通关秘籍》学习总结

2023-06-19 17:21| 来源: 网络整理| 查看: 265

最近在学习神光大神的《Nest通关秘籍》,该小册主要包含下面这些内容:

image.png 想购买的可以点击《传送门》。

接下来的日子里,我将更新一系列的学习笔记。感兴趣的可以关注我的专栏《Nest 通关秘籍》学习总结。

特别申明:本系列文章已经经过作者本人的允许。 大家也不要想着白嫖,我的笔记只是个人边学习边记录的,不是很完整,大家想要深入学习还是要自己去购买原版小册。

本章我们来学习nest中的五花八门的装饰器。

image.png

1.@module 声明Module import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; @Module({ imports: [], controllers: [AppController], providers: [AppService], }) export class AppModule {} 2.@Controller声明 Controller import { Controller, Get } from '@nestjs/common'; import { AppService } from './app.service'; @Controller() export class AppController { constructor(private readonly appService: AppService) {} @Get() getHello(): string { return this.appService.getHello(); } } 3.@Injectable声明 Provider import { Injectable } from '@nestjs/common'; @Injectable() export class AppService { getHello(): string { return 'Hello World!'; } } 4.@Inject指定注入的 token ... @Controller() export class AppController { @Inject('app_service') private readonly appService: AppService; @Get() getHello(): string { return this.appService.getHello(); } } // or ... @Controller() export class AppController { constructor(@Inject('app_service') private readonly appService: AppService) {} @Get() getHello(): string { return this.appService.getHello(); } } ... 5.@Optional声明为可选的 import { Controller, Get, Inject, Optional } from '@nestjs/common'; import { AppService } from './app.service'; @Controller() export class AppController { constructor(private readonly appService: AppService) {} @Optional() @Inject('xiumubai') private readonly xiumubai: Record; @Get() getHello(): string { return this.appService.getHello(); } } 6.@Global 把它声明为全局 import { Global, Module } from '@nestjs/common'; import { AaaService } from './aaa.service'; import { AaaController } from './aaa.controller'; @Global() @Module({ controllers: [AaaController], providers: [AaaService], exports: [AaaService], }) export class AaaModule {} 7.@Catch 来指定处理的异常

我们在aaa.filter.ts中通过@Catch处理抛出的未捕获异常

import { ArgumentsHost, Catch, ExceptionFilter, HttpException, } from '@nestjs/common'; import { Response } from 'express'; @Catch(HttpException) export class AaaFilter implements ExceptionFilter { catch(exception: HttpException, host: ArgumentsHost) { const response: Response = host.switchToHttp().getResponse(); response.status(exception.getStatus()).json({ msg: exception.message, }); } }

然后通过 @UseFilters 应用到 handler 上:

import { Controller, Get, UseFilters, HttpStatus, HttpException, } from '@nestjs/common'; import { AaaService } from './aaa.service'; import { AaaFilter } from './aaa.filter'; @Controller('aaa') export class AaaController { constructor(private readonly aaaService: AaaService) {} @Get() @UseFilters(AaaFilter) findAll() { throw new HttpException('xxx', HttpStatus.BAD_REQUEST); return this.aaaService.findAll(); } }

当访问,可以看到抛出的异常:

除了 filter 之外,interceptor、guard、pipe 也是这样用。

8.请求参数相关的装饰器

8.1 @Post

post请求可以通过@Body来获取body的部分:

@Post() create(@Body() createAaaDto: CreateAaaDto) { console.log(createAaaDto); return this.aaaService.create(createAaaDto); }

body参数的结构体一般使用dto来声明,nest 会实例化一个 dto 对象:

export class CreateAaaDto { age: number; name: string; }

发送一个post请求:

可以看到控制台接收到了一个body参数:

除了 @Post 外,还可以用 @Get、@Put、@Delete、@Patch、@Options、@Head 装饰器分别接受 get、put、delete、patch、options、head 请求。

9.@SetMetadata指定metadata // aaa.controller.ts import { Controller, Get, SetMetadata, UseGuards, } from '@nestjs/common'; import { AaaService } from './aaa.service'; import { CreateAaaDto } from './dto/create-aaa.dto'; import { UpdateAaaDto } from './dto/update-aaa.dto'; import { AaaGuard } from './aaa.guid'; @Controller('aaa') @SetMetadata('roles', ['user']) export class AaaController { constructor(private readonly aaaService: AaaService) {} @Get() @UseGuards(AaaGuard) @SetMetadata('roles', ['admin']) findAll() { return this.aaaService.findAll(); } } // aaa.guard.ts import { CanActivate, ExecutionContext, Inject, Injectable, } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import { Observable } from 'rxjs'; @Injectable() export class AaaGuard implements CanActivate { @Inject(Reflector) private readonly reflector: Reflector; canActivate( context: ExecutionContext, ): boolean | Promise | Observable { const classMetaDatas = this.reflector.get('roles', context.getClass()); const methodMetaDatas = this.reflector.get('roles', context.getHandler()); console.log(classMetaDatas, methodMetaDatas); return true; } }

10.@Headers获取请求头 @Get('/header') header( @Headers('Accept') accept: string, @Headers() headers: Record, ) { console.log('accept', accept); console.log('headers', headers); }

11.@Session拿到session对象

要使用 session 需要安装一个 express 中间件:

pnpm install express-session

在 main.ts 里引入并启用:

import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import * as session from 'express-session'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.use( session({ secret: 'xiumu', cookie: { maxAge: 1000 }, }), ); await app.listen(3000); } bootstrap();

发送一个请求

会返回 Set-Cookie 的响应头,设置了 cookie,包含 sid 也就是 sesssionid。

12.@HostParam获取域名部分的参数 import { Controller, Get, HostParam, } from '@nestjs/common'; import { BbbService } from './bbb.service'; @Controller({ host: ':host.0.0.1', path: 'bbb' }) export class BbbController { constructor( private readonly bbbService: BbbService, ) {} @Get('host') host(@HostParam('host') host) { return host; } }

这样只有通过xxx.0.0.1访问的才能通过。

13.@Req获取请求参数 @Get('req') getBbbb(@Req() req: Request) { console.log('req', req.hostname, req.url); }

14.自定义方法装饰器

之前我们用@SetMetadata设置了一些角色数据,然后通过Guard再判断逻辑。现在我们把@SetMetaData来自定义一下:

// bbb.decorator.ts import { SetMetadata } from '@nestjs/common'; export const Bbb = (...args: string[]) => SetMetadata('aaa', args);

然后在Controller中使用:

import { Controller, Get, HostParam, UseGuards, } from '@nestjs/common'; import { Request } from 'express'; import { BbbService } from './bbb.service'; import { Bbb } from './bbb.decorator'; import { BbbGuard } from './bbb.guard'; @Controller({ host: ':host.0.0.1', path: 'bbb' }) export class BbbController { constructor( private readonly bbbService: BbbService, ) {} @Get() @UseGuards(BbbGuard) @Bbb('admin') findAll() { return this.aaaService.findAll(); } }

这样我们可以使用上面的方式来使用这个装饰器。测试一下:

现在我们这里的装饰器有点多:

我们可以把这三个装饰合并成一个使用:

// merge.decorator.ts import { applyDecorators, Get, UseGuards } from '@nestjs/common'; import { Bbb } from './bbb.decorator'; import { BbbGuard } from './bbb.guard'; export function Merge(path, role) { return applyDecorators(Get(path), Bbb(role), UseGuards(BbbGuard)); }

使用的时候可以这样使用:

import { Controller, Get, HostParam, Req, UseGuards, } from '@nestjs/common'; import { Request } from 'express'; import { BbbService } from './bbb.service'; import { AaaService } from 'src/aaa/aaa.service'; import { Bbb } from './bbb.decorator'; import { BbbGuard } from './bbb.guard'; import { Merge } from './merge.decorator'; @Controller({ host: ':host.0.0.1', path: 'bbb' }) export class BbbController { constructor( private readonly bbbService: BbbService, private readonly aaaService: AaaService, ) {} @Get() @UseGuards(BbbGuard) @Bbb('admin') findAll() { return this.aaaService.findAll(); } @Merge('hello2', 'admin') getHello3(): string { return 'this is merge decorator'; } }

访问http://127.0.0.1:3000/bbb/hello2:

效果和之前一样。

15.自定义参数装饰器

先来写一个参数装饰器:

// ccc.decorator.ts import { createParamDecorator, ExecutionContext } from '@nestjs/common'; export const Ccc = createParamDecorator( (data: string, ctx: ExecutionContext) => { return 'ccc'; }, );

这样使用:

import { Controller, Get } from '@nestjs/common'; import { CccService } from './ccc.service'; import { Ccc } from './ccc.decorator'; @Controller('ccc') export class CccController { constructor(private readonly cccService: CccService) {} @Get('arg') getArg(@Ccc() c) { return c; } }

这里拿到的c就是参数装饰器的返回值。

在我们自定义的装饰器中,data 很明显就是传入的参数,而 ExecutionContext 前面用过,可以取出 request、response 对象。

这样,那些内置的 @Param、@Query、@Ip、@Headers 等装饰器,我们也可以自己实现了。

下面我们实现一个Header装饰器:

import { createParamDecorator, ExecutionContext } from '@nestjs/common'; import { Request } from 'express'; export const MyHeaders = createParamDecorator( (key: string, ctx: ExecutionContext) => { const request: Request = ctx.switchToHttp().getRequest(); return key ? request.headers[key] : request.headers; }, ); @Get('my') getHeader(@Headers('Accept') headers1, @MyHeaders('accept') headers2) { console.log('headers1', headers1); console.log('headers2', headers2); }

这里我们的@@MyHeaders和@Headers具有同样的效果,都能拿到Accept的值。

注意:@MyHeaders()接受的参数是accept,小写开头。

下面我们再实现一个query装饰器。

export const MyQuery = createParamDecorator( (key: string, ctx: ExecutionContext) => { const request: Request = ctx.switchToHttp().getRequest(); return request.query[key]; }, ); @Get('query') getHello6(@Query('aaa') aaa, @MyQuery('bbb') bbb) { console.log('aaa', aaa); console.log('bbb', bbb); }

我们通过断点调试的方式,来看看:

可以看到在request中,可以拿到query返回的参数,我们根据key值,取到返回了。

16.自定义class装饰器

同样的,class的装饰器也可以自定义:

// myHeaders.decorator.ts export const MyClass = () => Controller('class'); import { Controller, Get, Headers, Query } from '@nestjs/common'; import { CccService } from './ccc.service'; import { Ccc } from './ccc.decorator'; import { MyHeaders, MyQuery, MyClass } from './myHeaders.decorator'; // @Controller('ccc') @MyClass() export class CccController { constructor(private readonly cccService: CccService) {} @Get('arg') getArg(@Ccc() c) { return c; } @Get('my') getHeader(@Headers('Accept') headers1, @MyHeaders('Accept') headers2) { console.log('headers1', headers1); console.log('headers2', headers2); } @Get('query') getHello6(@Query('aaa') aaa, @MyQuery('bbb') bbb) { console.log('aaa', aaa); console.log('bbb', bbb); } }

我们把@Controller('ccc')替换成了@MyClass(),然后访问一下http://127.0.0.1:3000/class/query?aaa=aaa&bbb=bbb,同样也是没问题的。

总结:

内置装饰器不够用的时候,或者想把多个装饰器合并成一个的时候,都可以自定义装饰器。

方法的装饰器就是传入参数,调用下别的装饰器就好了,比如对 @SetMetadata 的封装。

如果组合多个方法装饰器,可以使用 applyDecorators api。

还可以通过 createParamDecorator 来创建参数装饰器,它能拿到 ExecutionContext,进而拿到 reqeust、response,可以实现很多内置装饰器的功能,比如 @Query、@Headers 等装饰器。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有