Skip to content

Nest.js入门 #24

@jiefancis

Description

@jiefancis

1. 路由Controller

路由注册

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

    }
  1. 通配符 *
    @Controller('admin')
    export const Controller{
        // 匹配admin/*所有路由下的get请求
        @Get('*')

    }
  1. 动态参数
    @Controller('admin')
    export const Controller{
        @Get(":id")
        @Bind(Param())
        async find(param) {  return { param } }

    }

获取请求参数

  1. get请求
@Param  获取动态参数
@Query  获取url?a=1&b=2中的a和b参数
@Req     获取request请求对象
   
  1. 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(){}
    }
  1. 动态设置 @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()以将控制权传递给下一个中间件函数。否则,请求将被挂起。
  1. 如何定义和使用?
    1. @Injectable()装饰器包裹
    2. implements NestMiddleware 实现中间件
  1. 用法
        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()
        }
  1. 多个中间件 && 多个路由
    @Injectable()
    class Module implements NestModule{
        constructor(consumer: NestMiddleware) {
            consumer.apply(logger1, logger2).forRoutes(
                'path1',
                'path2'
            )
        }
    }
  1. 应用场景(解决什么问题)
    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())

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions