Skip to content
On this page

完善接口

上一篇中定义初步接口的增删改查,这篇我们接着完善接口数据。

定义 DTO

DTO 全程 Data Transfer Object 即数据传输对象,在文章模块中定义 CreatePostDto 来约束数据

TS
class CreatePostDto {
    @ApiProperty({
        description: '文章标题',
        example: '标题',
    })
    title: string;
    @ApiProperty({ description: '文章内容', example: '内容' })
    content: string;
}

可以对属性进行描述,在接口中直接定义

TS
@Post()
@ApiOperation({
    summary: '创建文章',
})
async create(@Body() createPostDto: CreatePostDto) {
    const data = await PostModel.create(createPostDto);
    return {
        success: 0,
        data,
    };
}

在接口中看到存在 @Body 装饰器,这是获取 body 数据,其中还存在 @Query@Param 装饰器,看定义我们大概能知道其中的含义:

  • Body :获取 body 数据
  • Query:获取 query 数据
  • Param:获取 param

对应到接口上

TS
export class PostsController {
    @Get()
    @ApiOperation({
        summary: '获取文章列表数据',
    })
    findAll() {
        return [
            {
                id: 1,
                title: '标题'
            }
        ];
    }

    @Post()
    @ApiOperation({
        summary: '创建文章',
    })
    create(@Body() createPostDto: CreatePostDto) {
        return {
            success: 0,
        };
    }

    @Get(':id')
    @ApiOperation({
        summary: '获取文章详情',
    })
    async detail(@Param('id') id: string) {
        return {
		success: 0,
	};
    }

    @Put(':id')
    @ApiOperation({
        summary: '编辑文章',
    })
    update(
        @Param('id') id: string,
        @Body() createPostDto: CreatePostDto
    ) {
        return {
            success: 0,
        };
    }

    @Delete(':id')
    @ApiOperation({
        summary: '删除文章',
    })
    remove(@Param('id') id: string) {
        return {
            success: 0,
        };
    }
}

连接数据库

接口我们都定义好后,可以连接数据库实现基础逻辑。这里使用 mongoose 数据库。在使用前需要安装依赖:

npm i @typegoose/typegoose mongoose @types/mongoose --save

注意:这里默认已安装 mongodb 数据库,未安装数据库请自行安装

在入口文件 main.ts 文件中连接数据库

TS
import * as mongoose from 'mongoose';

async function bootstrap() {
    mongoose.connect('mongodb://localhost/nestjs-test-api', {}, (err: any) => {
        if (err) {
            console.log(err, '数据库连接错误!');
        }
        console.log('数据库连接成功!');
    });
    ...
}
bootstrap();

定义 Model

数据库连接成功后,接下来需要定义数据 Model ,在 Posts 定义 post.model.ts 文件。

TS
import { getModelForClass, prop } from '@typegoose/typegoose';
export class Post {
    @prop()
    title: string

    @prop()
    content: string
}

export const PostModel = getModelForClass(Post);

注意: model 定义推荐单数 post 定义

定义数据模型后,可以直接在控制器中使用,由于 TS 特性,完全可以自动识别到 mongodb 方法;可以简单的实现文章接口的增删改查

TS
import {
    Body,
    Controller,
    Delete,
    Get,
    Param,
    Post,
    Put,
    Query,
} from '@nestjs/common';
import { ApiOperation, ApiProperty, ApiTags } from '@nestjs/swagger';
import { PostModel } from './post.model';

class CreatePostDto {
    @ApiProperty({
        description: '文章标题',
        example: '标题',
    })
    title: string;
    @ApiProperty({ description: '文章内容', example: '内容' })
    content: string;
}

@Controller('posts')
@ApiTags('Posts')
export class PostsController {
    @Get()
    @ApiOperation({
        summary: '获取文章列表数据',
    })
    async index() {
        return await PostModel.find();
    }

    @Post()
    @ApiOperation({
        summary: '创建文章',
    })
    async create(@Body() createPostDto: CreatePostDto) {
        const data = await PostModel.create(createPostDto);
        return {
            success: 0,
            data,
        };
    }

    @Get(':id')
    @ApiOperation({
        summary: '获取文章详情',
    })
    async detail(@Param('id') id: string) {
        return await PostModel.findById(id);
    }

    @Put(':id')
    @ApiOperation({
        summary: '编辑文章',
    })
    async update(
        @Param('id') id: string,
        @Body() createPostDto: CreatePostDto
    ) {
        await PostModel.findByIdAndUpdate(id, createPostDto);
        const data = await PostModel.findById(id);
        return {
            success: 0,
            data,
        };
    }

    @Delete(':id')
    @ApiOperation({
        summary: '删除文章',
    })
    async remove(@Param('id') id: string) {
        const res = await PostModel.findByIdAndDelete(id);
        return {
            success: 0,
            data: res,
        };
    }
}

测试接口可以使用上一篇提到的 api-docs 地址,来查看接口是否添加成功。

数据验证

当前端传输数据给后端时,后端也要做数据的校验规则,不然传输什么就接受什么,对程序来说也是不健全的。下载相应的依赖

npm i class-validator class-transformer --save
  • class-validator 数据校验
  • class-transformer 数据转换

下载依赖后,需要在入口文件 main.ts 添加全局管道

TS
// 添加全局验证
app.useGlobalPipes(new ValidationPipe());

这里的管道相当于中间件,所有的输入输出都会要走管道逻辑。接着我们可以在 DTO 上装饰接口参数

TS
import { IsNotEmpty } from 'class-validator';
class CreatePostDto {
    @ApiProperty({
        description: '文章标题',
        example: '标题',
    })
    @IsNotEmpty({
        message: '请填写标题!',
    })
    title: string;
    @ApiProperty({ description: '文章内容', example: '内容' })
    content: string;
}

可以对参数的类型进行校验

image.png

总结

这篇完善了接口的增删改查,对接口的文档进行补充,接口参数怎么校验,数据库怎么连接操作;也看到 Nest 这个框架依赖于各种装饰器来简化我们的业务操作。