Skip to content

Nest.js 系列——编写 web 接口以及各种参数获取

一、前言

前面基本搭建了一个基本的开发接口的环境,但是有小伙伴说编写基本的 curd 接口部分不够详细,所以这次就详细的讲解一下,如何编写一个基本的 curd 接口。以及在编写接口的过程中,会遇到哪几种获取请求参数的方式。

二、编写接口

编写简单的接口一般会使用 nest cli 创建基础的文件。一种是模块、控制器、服务一个一个的创建,另一种是使用 nest cli 一次性创建。

bash
nest g module user
nest g controller user
nest g service user

当使用这个方式创建业务模块的时候,一定要注意顺序,因为顺序对了,会自动的在 app.module.ts 中引入模块,如果顺序不对,就需要手动引入了。

bash
nest g resource user

这里已经生成的有 user 模块了,就用 user1 做个例子

一般情况下,我们会使用第二种方式创建,因为这样可以一次性创建好模块、控制器、服务。看下生成的目录结构:

dto 文件夹是用来存放数据传输对象的,前面文章中也有写到,dto 主要是对数据进行校验

typescript
// src/user/dto/create-user.dto.ts
import { IsEmail, IsNotEmpty } from 'class-validator'

export class CreateUserDto {
  @IsEmail()
  email: string

  @IsNotEmpty()
  password: string
}

可以看到对前端传递过来的数据进行了校验也是在这里处理的,这样就不用在控制器中进行校验了,这样就可以让控制器更加的简洁。 entities 主要是用来存放实体的,是对数据库表的映射

typescript
// src/user/entities/user.entity.ts
export class User {
  id: number
  email: string
  password: string
}

然后接口的控制器主要是对参数的获取,然后调用服务层的方法,最后返回数据给前端

typescript
// src/user/user.controller.ts
import {
  Controller,
  Get,
  Post,
  Body,
  Patch,
  Param,
  Delete
  // HttpException,
} from '@nestjs/common'
import { UserService } from './user.service'
import { CreateUserDto } from './dto/create-user.dto'
import { UpdateUserDto } from './dto/update-user.dto'
import { ConfigService } from '@nestjs/config'

import { ApiOperation, ApiTags } from '@nestjs/swagger'

@ApiTags('用户')
@Controller('user')
export class UserController {
  constructor(private readonly userService: UserService, private configService: ConfigService) {}

  @ApiOperation({ summary: '创建用户' })
  @Post()
  create(@Body() createUserDto: CreateUserDto) {
    return this.userService.create(createUserDto)
  }

  @ApiOperation({ summary: '用户列表' })
  @Get()
  findAll() {
    return this.userService.findAll()
  }

  @ApiOperation({ summary: '用户详情' })
  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.userService.findOne(+id)
  }

  @ApiOperation({ summary: '修改用户' })
  @Patch(':id')
  update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
    return this.userService.update(+id, updateUserDto)
  }

  @ApiOperation({ summary: '删除用户' })
  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.userService.remove(+id)
  }
}

然后服务层主要是对数据库的操作,这里使用的是 typeorm,所以可以直接使用 typeorm 的方法,这里就不多说了

typescript
// src/user/user.service.ts
import { Injectable } from '@nestjs/common'
import { CreateUserDto } from './dto/create-user.dto'
import { UpdateUserDto } from './dto/update-user.dto'
import { Repository } from 'typeorm'
import { User } from './entities/user.entity'
import { InjectRepository } from '@nestjs/typeorm'

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User)
    private userRepository: Repository<User>
  ) {}
  create(createUserDto: CreateUserDto) {
    return 'This action adds a new user'
  }

  findAll() {
    return `This action returns all user`
  }

  findOne(id: number) {
    return `This action returns a #${id} user`
  }

  update(id: number, updateUserDto: UpdateUserDto) {
    return `This action updates a #${id} user`
  }

  remove(id: number) {
    return `This action removes a #${id} user`
  }
}

这里的服务就是对数据库里面的数据进行操作,这里使用的是 typeorm,所以可以直接使用 typeorm 的方法。这里只是简单的返回了一些字符串,实际开发中是需要对数据库进行操作的。后面在接入数据库的时候单独讲解。

很多时候可能不想生成测试文件,其实这个是可以通过配置或者命令行参数来控制的,在生成业务模块的时候不生成测试文件,可以使用下面的命令:

bash
nest g resource user --no-spec

如果是配置的化可以在 nest-cli.json 中进行配置,这样就不用每次执行命令都带参数了

json
{
  "generateOptions": {
    "spec": false
  }
}

三、请求中的参数获取方式

其实在平常的开发中,前后端传递参数的方式主要有 5 种

  • url param
  • query
  • form-urlencoded
  • form-data
  • json

那么这 5 种数据传输的各种表现形式是什么样子的呢?用几个例子来说明一下

3.1 url param

url param 是指的是 url 中的参数,比如下面的例子

可以看下控制器中通过 @Param()装饰器获取到了 url 中的参数

ts
@Get(':id')
findOne(@Param('id') id: string) {
  return `后端接收的url param参数:${id}`;
}

3.2 query

query 是指的是 url 中?后面的查询参数,比如下面的例子

bash
@Get('find')
  query(@Query('name') name: string, @Query('age') age: number) {
    return `后端接收的query参数: name=${name},age=${age}`;
  }

3.3 form-urlencoded

form-urlencoded 是指的是表单提交的数据,比如下面的例子 通过 body 装饰器能拿到请求的参数

ts
@Post()
body(@Body() createUserDto: CreateUserDto) {
  return `后端接收到的body参数: ${JSON.stringify(createUserDto)}`;
}

// 拿到的参数
{
  "name": "water",
  "age": 18
}

3.4 json

json 是指的是 json 格式的数据,不用设置,默认就是 json 格式的数据

ts
@Post()
body(@Body() createUserDto: CreateUserDto) {
  return `后端接收到的body参数: ${JSON.stringify(createUserDto)}`;
}

可以看出和上一种获取参数的方式相同都是使用 @Body()装饰器获取参数,而且一般这个 json 的方式比较常用

3.5 form-data

form-data 一般用来作为文件传输的场景比较到,比如上传文件,这里就演示下如果在 nest 中上传文件,并用 form-data 的方式 需要安装一个包

bash
npm i -D @types/multer

这个是专门用来做文件上传的

ts
@Post('file')
  @UseInterceptors(
    AnyFilesInterceptor({
      dest: 'uploads/',
    }),
  )
  file(
    @Body() createUserDto: CreateUserDto,
    @UploadedFiles() files: Array<Express.Multer.File>,
  ) {
    console.log(files);
    return `received: ${JSON.stringify(createUserDto)}`;
  }

通过 @UploadedFiles()装饰器获取到上传的文件

小结

通过这些方式技能简单的生成一个业务接口的模块代码,而且通过每种传递参数的方式都有对应的装饰器去获取参数,总体处理起来很方便,有什么不对的地方欢迎指正。希望对你有所帮助,谢谢!

如有转载或 CV 的请标注本站原文地址