jiefancis / blogs

个人博客,学习笔记(issues)
1 stars 0 forks source link

Nest.js入门 #24

Open jiefancis opened 2 years ago

jiefancis commented 2 years ago

1. 路由Controller

路由注册

  1. /admin支持get和post请求
    @Controller('admin')
    export const Controller{
        @Get()
        async find() {}
        @Post()
        async find() {}
    }
  2. 接口地址为:admin/demo

    @Controller('admin')
    export const Controller{
        @Get('demo')
    
    }
  3. 通配符 *

    @Controller('admin')
    export const Controller{
        // 匹配admin/*所有路由下的get请求
        @Get('*')
    
    }
  4. 动态参数

    @Controller('admin')
    export const Controller{
        @Get(":id")
        @Bind(Param())
        async find(param) {  return { param } }
    
    }

    获取请求参数

  5. get请求
    
    @Param  获取动态参数
    @Query  获取url?a=1&b=2中的a和b参数
    @Req     获取request请求对象
2. post请求

@Body 解析body数据 @Controller('admin') export const Controller{ @POST() @Bind(Body()) async find(data) { return { data} } }


## 设置响应状态码
1. HttpCode
@Controller()
export const Controller{
    @Get('admin')
    @HttpCode(200)
    async function(){}
}
4. 动态设置 @Res

res.status(HttpStatus.CREATED).send(返回数据)


# 2. services服务

import { Injectable } from '@nestjs/common'; type Users = Array<Record<any, any>>;

@Injectable() export class UserService { private users: Users = [{ name: '1' }, { name: 2 }];

queryUser(): Users { return this.users; } }

# 3. Module模块 
模块作为组织组件的有效方式;每个模块有自己的 .service 和 .controller 和 .module文件,在.module模块中引入service(providers)和controller(controllers)供实例化
## 

    # 最后在根模块 app.module中引入模块注册
    @Module({
        imports: [UserModule]
    })

    # 共享模块(共享同一个实例)
    @@filename('user.module')
    @Module({
        exports: [UserService],
        controllers: [UserController],
        providers: [UserService]
    })

    现在任何导入UserModule的模块CatsModule都可以访问CatsService并且将与导入它的所有其他模块共享相同的实例

    # 导出导入的模块
    @filename('user.module')
    @Module({
        imports: [AdminModule],
        exports: [AdminModule]
    })

    # 全局模块 @Global()

    # 动态模块???

# 4. 中间件 middleware

在路由处理程序**之前调用的函数**;可以访问**请求**和**响应**对象。

## 功能(起什么作用)
  1. 中间件函数可以执行以下任务:

    • 执行任何代码。
    • 更改请求和响应对象。
    • 结束请求-响应周期。
    • 调用堆栈中的下一个中间件函数。
    • 如果当前中间件函数没有结束请求-响应循环,它必须调用next()以将控制权传递给下一个中间件函数。否则,请求将被挂起。
  2. 如何定义和使用?

    1. @Injectable()装饰器包裹
    2. implements NestMiddleware 实现中间件
  3. 用法

        1. 针对部分路由  
            - consumer.apply(middleware).forRoutes('user'或者UserController)
    
            - 同一个路由,对get操作使用中间件过滤
            consumer.apply(middleware).forRoutes({ path: 'cats', method: RequestMethod.GET })
    
            - 多个路由
                consumer.apply(middleware).forRoutes(
                    { path: 'cats', method: RequestMethod.GET },
                    { path: 'admin', method: RequestMethod.GET }
                )
    
                consumer.apply(middleware).forRoutes(
                    CatController,
                    AdminController
                )
    
        2. 全局中间件
            @@filename('app.module')
            forRoutes('*')
    
        3. 忽略
        consumer.apply().exclude()
    
        5. 功能中间件(定义为一个方法)
        function logger(req, res, next) {
            console.log('functional middleware')
            next()
        }
  4. 多个中间件 && 多个路由

    @Injectable()
    class Module implements NestModule{
        constructor(consumer: NestMiddleware) {
            consumer.apply(logger1, logger2).forRoutes(
                'path1',
                'path2'
            )
        }
    }
  5. 应用场景(解决什么问题)

    1. 日志收集(每个请求都经过中间件,拦截器也可以吧?)

5. 异常过滤器(捕获未处理异常)?日志?

内置异常HttpException

```
@@filename(cats.controller)
@Get()
async findAll() {
throw new HttpException({
    status: HttpStatus.FORBIDDEN,
    error: 'This is a custom message',
}, HttpStatus.FORBIDDEN);
}
```

# 自定义
export class ForbiddenException extends HttpException{
    constructor() {
        super('Forbidden', HttpStatus.FORBIDDEN)
    }
}
无需引入,跟HttpException可在任意地方使用

6. 管道(实现PipeTransform接口)

# 应用场景
- 转换(将输入数据转换为需要的格式)
- 验证(校验输入数据是否有效)

# 执行时机
- 在调用方法之前对数据进行处理

# 全局管道和局部管道
@@filename('app.module')
useGlobalPipes()

@UsePipes(new Pipe(validateSchema))

# 例子
```
import { IsString, IsInt } from 'class-validator';

export class CreateCatDto {
    @IsString()
    name: string;

    @IsInt()
    age: number;

    @IsString()
    breed: string;
}

@Post()
async create(
    @Body(new ValidationPipe()) createCatDto: CreateCatDto,
)
{
    this.catsService.create(createCatDto);
}

@Post()
@UsePipes(new JoiValidationPipe(createCatSchema))
async create(@Body() createCatDto: CreateCatDto) {
    this.catsService.create(createCatDto);
}

```

7. Guards警卫

# 为什么不用中间件?

1. 授权,决定用户是否可访问。

# 全局守卫和局部守卫

@@filename('app.module')
app.useGlobalGuards(new RoleGuards())