• Nest基础学习


    基础部分

    nestjs 一切都是以模块为基础的。用module一般用来组织架构。

    module一半儿以**@Module**装饰器注,内容有四部分,imports ,controllers, providers, exports.

    • imports
      导入其他模块的module。一般在app.module.ts中导入所有你开发的其他功能的module

    • controller
      一般是写明自己模块的controller,让nest知道那些controller应该被安装

    • providers
      provider - service, repository, factory, helper 等等都可认为是provider,写明便于nest自动注入

    • exports
      一般导出自己模块的providers中内容,即service供其他模块使用

    ** 具体使用 **

    • 导入
    @Module({
      // imports:[CatsModule.forRoot()] 引入并使用
      imports: [CatsModule],
      controllers: [AppController],
      providers: [{provide:APP_FILTER,useClass:HttpExceptionFilter},AppService,],
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 导出
    @Module({
      controllers: [CatsController],
      providers: [CatsService], // 组织程序架构
      exports: [CatsService], // 导出其他模块可以使用
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5

    中间件

    中间件是在路由处理程序 之前 调用的函数

    作用

    • 执行任何代码。
    • 对请求和响应对象进行更改。
    • 结束请求-响应周期
    • 调用堆栈中的下一个中间件函数
    • 中间件函数没有结束请求-响应周期, 它必须调用 next() 将控制传递给下一个中间件函数。否则, 请求将被挂起。

    开发

    • 类中间件
      @Injectable() 装饰器
      实现NestMiddleware接口实现use(req,res,next)
    • 函数中间件
      直接导出一个函数,也具有req,res,next三个函数

    ** 实现**

    • 类中间件
    @Injectable()
    export class LoggerMiddleware implements NextMiddleware {
      use(req: Request, res: Response, next: NextFunction) {
        next();
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 函数中间件
    export function logger(res, req, next) {
      console.log(res);
      next();
    }
    
    • 1
    • 2
    • 3
    • 4

    使用

    • 在app.module.ts中使用configure方法来应用中间件并指定应用路由
      apply方法可以应用多个中间件apply(cors(), helmet(), logger)
      configure(consumer: MiddlewareConsumer) {
        // consumer.apply(LoggerMiddleware).forRoutes('cats'); //  限定特定路由
        // consumer.apply(LoggerMiddleware).forRoutes({path;'cats',method:RequestMethod.GET})
        consumer
          .apply(LoggerMiddleware)
          .exclude(
            { path: 'cats', method: RequestMethod.GET },
            { path: 'cats', method: RequestMethod.POST }, // 使用  path-to-regexp 支持通配符
            'cats/(.*'),
          )
          .forRoutes(CatsController);
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 直接全局使用,main.ts中使用app.use()
    async function bootstrap() {
      const app = await NestFactory.create(AppModule);
      app.use(logger); //全局使用
      await app.listen(3000);
    }
    bootstrap();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    异常过滤器

    内置的异常层负责处理整个应用程序中的所有抛出的异常。当捕获到未处理的异常时,最终用户将收到友好的响应。

    基本异常类

    • 内置了HttpException
    @Get()
    async findAll() {
      throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 自定义异常需extend HttpException
    export class ForbiddenException extends HttpException {
      constructor() {
        super('Forbidden', HttpStatus.FORBIDDEN);
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    异常过滤器

    对异常层拥有完全控制权.
    基于某些动态因素添加日志记录或使用不同的 JSON 模式,

    ** 开发 **

    • @Catch(HttpException)装饰器,告诉nest寻找特定的httpException的异常,设置为@Catch()所有异常
    • 实现ExceptionFilter中 catch(exception: HttpException, host: ArgumentsHost) 方法
    @Catch()
    export class AllExceptionFilter
      extends BaseExceptionFilter
      implements ExceptionFilter
    {
      catch(exception: unknown, host: ArgumentsHost) {
        const ctx = host.switchToHttp();
        const res = ctx.getResponse();
        const req = ctx.getRequest();
        const status =
          exception instanceof HttpException
            ? exception.getStatus()
            : HttpStatus.INTERNAL_SERVER_ERROR;
        res.status(status).json({
          statusCode: status,
          timestamp: new Date().toISOString(),
          path: req.url,
        });
        super.catch(exception, host);
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    ** 使用 **

    • 类和方法级别
      @UseFilters(HttpExceptionFilter) 方法 和类级别
    • 全局
      main.ts 中 useGlobalFilters(new HttpExceptionFilter())全局
    async function bootstrap() {
      const app = await NestFactory.create(AppModule);
       app.useGlobalFilters(new HttpExceptionFilter());
      await app.listen(3000);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    管道

    作用

    • 转换:管道将输入数据转换为所需的数据输出(例如,将字符串转换为整数)
    • 验证:对输入数据进行验证,如果验证成功继续传递; 验证失败则抛出异常

    开发

    • @Injectable()
    • 实现PipeTransform接口中 transform(value: any, metadata: ArgumentMetadata)方法
    @Injectable()
    export class ValidatePipe implements PipeTransform {
      // 自定义🇬🇺
      transform(value: any, { metatype }: ArgumentMetadata) {
        if (!metatype || !this.toValidate(metatype)) {
          return value;
        }
        const object = plainToInstance(metatype, value);
        const errors = await validate(object);
        if (errors.length > 0) {
          throw new BadRequestException('error');
        }
        return value;
      }
    
      private toValidate(metatype: Function): boolean {
        const types: Function[] = [String, Boolean, Number, Array, Object];
        return !types.includes(metatype);
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    使用

    • 参数上 参数上是有 findById(@Param(‘id’,ParseIntPipe) id: number){}自动转换 内置
    
      @Get('/name')
      //new DefaultValuePipe(false) 提供默认值
      async findOne (@Query('id',ParseIntPipe) id:number){//也可以是实例需要自定义报错信息的时候使用
        return this.catsService.findOne(id)
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 类和方法上
      @UsePipes(new JoiValidationPipe(createCatSchema))
    • 全局
      app.useGlobalPipes(new ValidationPipe()); 全局

    守卫

    它们根据运行时出现的某些条件(例如权限,角色,访问控制列表等)来确定给定的请求是否由路由处理程序处理。授权处理.

    开发

    • @Injectable() 装饰器
    • 实现 CanActivate 接口canActivate( context: ExecutionContext, )方法
    • 实现授权需要@SetMetadata(‘roles’, [‘admin’]) 来设置方法角色
    
    @Injectable()
    export class RolesGuard implements CanActivate {
      constructor(private reflector: Reflector) {}
    
      canActivate(context: ExecutionContext): boolean {
        const roles = this.reflector.get('roles', context.getHandler());
        if (!roles) {
          return true;
        }
        const request = context.switchToHttp().getRequest();
        const user = request.user;
        return matchRoles(roles, user.roles);
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    使用

    • 类or方法
      @UseGuards(RolesGuard)
    • 全局
      app.useGlobalGuards(new RolesGuard());

    拦截器

    作用

    • 在函数执行之前/之后绑定额外的逻辑
    • 转换从函数返回的结果
    • 转换从函数抛出的异常
    • 扩展基本函数行为
    • 根据所选条件完全重写函数 (例如, 缓存目的)

    开发

    • @Injectable() 装饰器注解
    • 实现 NestInterceptor 接口
    • 实现 intercept(context: ExecutionContext, next: CallHandler): Observable
      next.handle()返回一个流,可以在next.handle.pipe()中使用 catchError(err => throwError(new BadGatewayException()))来覆盖抛出的异常。也可以在pipe中使进行超时判定
    @Injectable()
    export class transformInterceptor
      implements NestInterceptor>
    {
      intercept(
        context: ExecutionContext,
        next: CallHandler,
      ): Observable | Promise> {
        return next.handle().pipe(
          map((data) => {
            {
              data;
            }
          }),
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    使用

    • 类or方法
      @UseInterceptors(LoggingInterceptor)
    • 全局
      app.useGlobalInterceptors(new LoggingInterceptor());

    自定义装饰器

    内置装饰器

    nest内置了很多 @Req @ Res @Body等参数装饰器

    自定义装饰器
    • 使用 createParamDecorator((data: unknown, ctx: ExecutionContext)方法创造及返回
    export const User = createParamDecorator((data: string, ctx: ExecutionContext) => {
      const request = ctx.switchToHttp().getRequest();
      const user = request.user;
    
      return data ? user && user[data] : user;
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 聚合装饰器
      applyDecorators 可以使用多个装饰器
    
    export function Auth(...roles: Role[]) {
      return applyDecorators(
        SetMetadata('roles', roles),
        UseGuards(AuthGuard, RolesGuard),
        ApiBearerAuth(),
        ApiUnauthorizedResponse({ description: 'Unauthorized"' })
      );
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 使用@来直接使用哦
    @Auth('admin') 
    
    • 1
  • 相关阅读:
    【web前端期末大作业】基于html+css+javascript+jquery技术设计的音乐网站(44页)
    适合学生党的百元蓝牙耳机,蓝牙耳机平价推荐
    机器学习算法基础--K-means应用实战--图像分割
    Cobalt Strike
    Hive高手之路:二、hive数据分析实验
    企业如何招聘高级前端工程师?
    【C++编程能力提升】
    47. 全排列 II
    为什么浏览器控制台(Console)运行JavaScript代码有时会出现“undefined”?
    [附源码]计算机毕业设计JAVA闲置物品交易管理系统
  • 原文地址:https://blog.csdn.net/qq_39692513/article/details/126852241