Nest的核心概念是提供一种体系结构,它帮助开发人员实现层的最大分离,并在应用程序中增加抽象。
主要有三个核心概念:模块Module, 控制器Controller, 服务与依赖注入 Provider Dependency injection
其他概念:
客户端请求 —> 中间件 —> 守卫 —> 拦截器之前 —> 管道 —> 控制器处理并响应 —> 拦截器之后 —> 过滤器
nest -h指令介绍
class (简写: cl) 类
controller (简写: co) 控制器
decorator (简写: d) 装饰器
exception (简写: e) 异常捕获
filter (简写: f) 过滤器
gateway (简写: ga) 网关
guard (简写: gu) 守卫
interceptor (简写: i) 拦截器
middleware (简写: mi) 中间件
module (简写: mo) 模块
pipe (简写: pi) 管道
provider (简写: pr) 供应商
service (简写: s) 服务
nest 利用cli创建,会自动生成并引入模块,
npm i -g @nestjs/cli
nest new project-name
npm start
nest generate module news
简写
nest g mo news
news.module.ts
import { Module } from '@nestjs/common';
import { NewsService } from './news.service';
import { NewsController } from './news.controller';
//创建时会自动引入到module中管理,同时会把module导入到app.module中
@Module({
providers: [NewsService],
controllers: [NewsController]
})
export class NewsModule {}
nest generate controller news
简写
nest g co news
news.controller.ts
import { Controller, Get } from '@nestjs/common';
import { NewsService } from './news.service';
@Controller()
export class AppController {
constructor(private readonly appService: NewsService) {} //将news.serbice中注入的属性,在这里注册就可以在this上使用
@Get()
getHello(): string {
return this.NewsService.getHello();
}
}
nest generate service cats
简写
nest g s cats
news.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()//注入到底层,在controller中就可以使用
export class NewsService {
getHello(): string{
return 'Hello World!';
}
}
app.module.ts
这部分很关键,需要将controllers引入,等同于加入路由操作
如果使用了service 也需要在下面引用,
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { DbModule } from '@libs/db';
import { NewsController } from './news/news.controller';
import { NewsService } from './news/news.service';
@Module({
imports: [
DbModule
],
controllers: [AppController,NewsController ],
providers: [AppService,NewsService],
})
export class AppModule {}
npm install --save @nestjs/swagger swagger-ui-express
安装过程完成后,打开main.ts文件并使用SwaggerModule类初始化Swagger:
import { NestFactory } from '@nestjs/core';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const options = new DocumentBuilder()
.setTitle('nest博客api') //标题
.setDescription('我的第一个nest项目') //描述
.setVersion('1.0') //版本
//.addTag('cats') //添加标签
.build();
const document = SwaggerModule.createDocument(app, options);
SwaggerModule.setup('api-doc', app, document);//定义挂载到那个路径下
await app.listen(3000);
console.log('http://localhost:3000/api-doc')
}
bootstrap();
结合swagger使用 文档
//参数装饰器
//@Body(key?:string),@Query(key?:string),@Param(key?:string)
等同于 res.body[key] 指定获取某一值
import { Controller, Get, Post, Body, Query, Param, Put, Delete } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiProperty,ApiQuery,ApiCreatedResponse, ApiParam } from '@nestjs/swagger';
import { query } from 'express';
// 这里不使用interface 原因是 interface编译成js后会被删除,同时用不了装饰器,无法在swagger显示
class CreatePostDto{ //用于对参数的限制
@ApiProperty({description:'帖子标题',example:'111'})
title:string
@ApiProperty({description:'帖子内容',example:'222'})
content:string
}
@Controller('posts') //相当于添加一个路由前缀
@ApiTags('帖子') //添加一个api标签
export class PostsController {
@Get()
@ApiOperation({summary:'显示博客列表'})//Api注解
// 帖子列表页
@ApiQuery({ name: 'id',example:1,description:'列表id'})
index(@Query()query){
return[
{id:1,title:'博客1'},
{id:1,title:'博客2'},
{id:1,title:'博客3'},
]
}
@Post()
@ApiOperation({summary:'创建帖子'})
@ApiCreatedResponse({ //编写响应的api注解
status:200,
description: 'The record has been successfully created.',
type: CreatePostDto,
})
create(@Body()createPostDto:CreatePostDto){
return{
data:createPostDto,
success:true
}
}
//params 和query获取的都是一个对象,可以在装饰器中指定获取的参数
@Get(':id')
@ApiParam({ name: 'id',example:1,description:'帖子id'})
@ApiOperation({summary:'获取帖子详情'})
async detail(@Param('id')id:string){
return {
data:data,
success:true
}
}
@Put(':id')
@ApiOperation({summary:'修改帖子详情'})
updatePostDto(@Param()id,@Body() updatePostDto:CreatePostDto){
return {
data:{
id:id.id,
data:updatePostDto
},
success:true
}
}
@Delete(':id')
@ApiOperation({summary:'删除帖子'})
remove(@Param()param){
return{
data:param.id,
success:true
}
}
}
RESTful接口规范 GET/POST/PUT/DELETE
REST 是Representational State Transfer的缩写,翻译是”表现层状态转化”.
面向资源是REST最明显的特征,对于同一个资源的一组不同的操作。资源是服务器 上一个可命名的抽象概念,资源是以名词为核心来组织的,首先关注的是名词。REST要求,必须通过统一的接口来对资源执行各种操作。对于每个资源只能执行一组有限的操作。
get 获取 post 创建 put 更新 delete 删除
状态码
200(OK) - 表示已在响应中发出
204(无内容) - 资源有空表示
301(Moved Permanently) - 资源的URI已被更新 303(See Other) - 其他(如,负载均衡)
304(not modified)- 资源未更改(缓存)
400 (bad request)- 指代坏请求(如,参数错误) 404 (not found)- 资源不存在
406 (not acceptable)- 服务端不支持所需表示
500 (internal server error)- 通用错误响应
503 (Service Unavailable)- 服务端当前无法处理请求
在根目录新建public文件夹
main.ts
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>( //注入平台
AppModule,
);
app.useStaticAssets(join(__dirname, '..', 'public'));//配置静态资源
// 或者
// app.useStaticAssets('public',{
// prefix:'/static/' //配置虚拟目录 上面一样
// })
app.setBaseViewsDir(join(__dirname, '..', 'views'));//配置模板文件存储文件夹
app.setViewEngine('ejs');//配置模板引擎需要安装不需要引入
await app.listen(3000);
}
bootstrap();
在根目录创建views文件夹,然后在下面创建index.ejs
之后在需要的controller中引入,
import { Controller, Post, Render, Get } from '@nestjs/common';
import { NewsService } from './news.service';
@Controller('news')
export class NewsController {
constructor(private readonly newsSerbice:NewsService){}
@Get()
@Render('index')
getEl(){
return {} //要么没有返回值,要么返回一个json
}
}
在一个nest项目创建同级项目中统一管理
cd project-name
nest g app children
//或者
nest g 整体项目名 子项目名
指定子项目中增加模块/控制器
nest g mo/co/s -p 子项目名 模块名
neest g mo -p admin users
这个时候在整体项目下会出现2个子项目这个时候的启动命令变成
//dev时需要加-w监听,子项目名是什么就会监听谁
nest start -w chidren-name
//创建一个db公用库
nest g lib db
//默认是@app, 最好改成@libs方便记忆
? What prefix would you like to use for the library (default: @app)? @libs
安装完成后在需要使用的模块的app.module.ts中引入dbmodule
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { DbModule } from '@libs/db';
@Module({
imports: [
DbModule
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
在lib文件下的src下的db.module.ts中连接数据库
import { Module } from '@nestjs/common';
import { DbService } from './db.service';
import { TypegooseModule } from "nestjs-typegoose"
@Module({
imports:[
TypegooseModule.forRoot("mongodb://localhost:27017/nest-MDemo",{
useNewUrlParser:true,
useUnifiedTopology: true,
useCreateIndex: true,
useFindAndModify: false
})
],
providers: [DbService],
exports: [DbService],
})
export class DbModule {}
然后在src下创建文件夹models 例如:创建一个user.model.ts
import {prop} from "@typegoose/typegoose"
export class User {
@prop()
username:string
@prop()
password:string
}
注册模块(可以在需要的模块中注册,也可以这样全局注册,就可以任意使用)
import { Module, Global } from '@nestjs/common';
import { DbService } from './db.service';
import { TypegooseModule } from "nestjs-typegoose"
import { User } from './models/user.model';
const models = TypegooseModule.forFeature([User])//注册模块
@Global()//定义为全局
@Module({
imports:[
TypegooseModule.forRoot("mongodb://localhost:27017/nest-MDemo",{
useNewUrlParser:true,
useUnifiedTopology: true,
useCreateIndex: true,
useFindAndModify: true
}),
models
],
providers: [DbService],
exports: [DbService,models],
})
export class DbModule {}
使用方式和单个项目一样 需要把lib下定义的user.model 导入然后注入