Nest.js 系列——编写 web 接口以及各种参数获取
一、前言
前面基本搭建了一个基本的开发接口的环境,但是有小伙伴说编写基本的 curd 接口部分不够详细,所以这次就详细的讲解一下,如何编写一个基本的 curd 接口。以及在编写接口的过程中,会遇到哪几种获取请求参数的方式。
二、编写接口
编写简单的接口一般会使用 nest cli 创建基础的文件。一种是模块、控制器、服务一个一个的创建,另一种是使用 nest cli 一次性创建。
nest g module user
nest g controller user
nest g service user
当使用这个方式创建业务模块的时候,一定要注意顺序,因为顺序对了,会自动的在 app.module.ts 中引入模块,如果顺序不对,就需要手动引入了。
nest g resource user
这里已经生成的有 user 模块了,就用 user1 做个例子
一般情况下,我们会使用第二种方式创建,因为这样可以一次性创建好模块、控制器、服务。看下生成的目录结构:
dto 文件夹是用来存放数据传输对象的,前面文章中也有写到,dto 主要是对数据进行校验
// src/user/dto/create-user.dto.ts
import { IsEmail, IsNotEmpty } from 'class-validator'
export class CreateUserDto {
@IsEmail()
email: string
@IsNotEmpty()
password: string
}
可以看到对前端传递过来的数据进行了校验也是在这里处理的,这样就不用在控制器中进行校验了,这样就可以让控制器更加的简洁。 entities 主要是用来存放实体的,是对数据库表的映射
// src/user/entities/user.entity.ts
export class User {
id: number
email: string
password: string
}
然后接口的控制器主要是对参数的获取,然后调用服务层的方法,最后返回数据给前端
// 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 的方法,这里就不多说了
// 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 的方法。这里只是简单的返回了一些字符串,实际开发中是需要对数据库进行操作的。后面在接入数据库的时候单独讲解。
很多时候可能不想生成测试文件,其实这个是可以通过配置或者命令行参数来控制的,在生成业务模块的时候不生成测试文件,可以使用下面的命令:
nest g resource user --no-spec
如果是配置的化可以在 nest-cli.json 中进行配置,这样就不用每次执行命令都带参数了
{
"generateOptions": {
"spec": false
}
}
三、请求中的参数获取方式
其实在平常的开发中,前后端传递参数的方式主要有 5 种
- url param
- query
- form-urlencoded
- form-data
- json
那么这 5 种数据传输的各种表现形式是什么样子的呢?用几个例子来说明一下
3.1 url param
url param 是指的是 url 中的参数,比如下面的例子
可以看下控制器中通过 @Param()装饰器获取到了 url 中的参数
@Get(':id')
findOne(@Param('id') id: string) {
return `后端接收的url param参数:${id}`;
}
3.2 query
query 是指的是 url 中?后面的查询参数,比如下面的例子
@Get('find')
query(@Query('name') name: string, @Query('age') age: number) {
return `后端接收的query参数: name=${name},age=${age}`;
}
3.3 form-urlencoded
form-urlencoded 是指的是表单提交的数据,比如下面的例子 通过 body 装饰器能拿到请求的参数
@Post()
body(@Body() createUserDto: CreateUserDto) {
return `后端接收到的body参数: ${JSON.stringify(createUserDto)}`;
}
// 拿到的参数
{
"name": "water",
"age": 18
}
3.4 json
json 是指的是 json 格式的数据,不用设置,默认就是 json 格式的数据
@Post()
body(@Body() createUserDto: CreateUserDto) {
return `后端接收到的body参数: ${JSON.stringify(createUserDto)}`;
}
可以看出和上一种获取参数的方式相同都是使用 @Body()装饰器获取参数,而且一般这个 json 的方式比较常用
3.5 form-data
form-data 一般用来作为文件传输的场景比较到,比如上传文件,这里就演示下如果在 nest 中上传文件,并用 form-data 的方式 需要安装一个包
npm i -D @types/multer
这个是专门用来做文件上传的
@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()装饰器获取到上传的文件
小结
通过这些方式技能简单的生成一个业务接口的模块代码,而且通过每种传递参数的方式都有对应的装饰器去获取参数,总体处理起来很方便,有什么不对的地方欢迎指正。希望对你有所帮助,谢谢!