一、官网
一定要认真学习官网内容!
NestJS 简介 | NestJS 中文文档 | NestJS 中文网
NestJS - A progressive Node.js framework
二、理解NestJS(内容来自官网)
2.1、理解NestJS
Nest (NestJS) 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的开发框架。它利用 JavaScript 的渐进增强的能力,使用并完全支持 TypeScript (仍然允许开发者使用纯 JavaScript 进行开发),并结合了 OOP (面向对象编程)、FP (函数式编程)和 FRP (函数响应式编程)。
在底层,Nest 构建在强大的 HTTP 服务器框架上,例如 Express (默认),并且还可以通过配置从而使用 Fastify !
Nest 在这些常见的 Node.js 框架 (Express/Fastify) 之上提高了一个抽象级别,但仍然向开发者直接暴露了底层框架的 API。这使得开发者可以自由地使用适用于底层平台的无数的第三方模块。
2.2、NestJS哲学
近年来,由于 Node.js、JavaScript 已经成为 web 前端和后端应用程序的“通用开发语言”。这促成了诸如 Angular、React 和 Vue 等优秀项目的出现,他们提高了开发者的工作效率,并能够创建快速、可测试和可扩展的前端应用程序。然而,尽管 Node (和服务器端 JavaScript)拥有大量优秀的软件库、辅助程序和工具,但没有一个能够有效地解决我们所面对的主要问题,即 架构。这样也是本人很长时间以来期望的。
Nest 提供了一个开箱即用的应用程序体系结构,允许开发者及其团队创建高度可测试、可扩展、松散耦合且易于维护的应用程序。这种架构深受 Angular 的启发。
2.3、NestJS能力
1、后端开发。
2、其他。
node.js可以做什么 • Worktile社区
2.4、NestJS对比Egg.js
三、安装、启动NestJS项目
NestJS 简介 | NestJS 中文文档 | NestJS 中文网
3.1、创建一个新的项目目录
创建一个新的项目目录并使用核心的 Nest 文件和支撑模块填充该目录,从而为项目创建一个传统的基本结构。建议初学者使用 Nest CLI 创建新项目。
npm i -g @nestjs/cli
cnpm i -g @nestjs/cli // 如速度慢可使用cnpm
nest new project-name
3.2、启动项目
pnpm run start
启动成功
3.3、从src/main.ts文件,我们看到项目监听的是3000端口
我们访问本地项目 http://localhost:3000/
访问成功
四、NestJS项目目录介绍
引用自技术胖-NestJS 快速入门教程
+-- dist[目录] // 编译后的目录,用于预览项目
+-- node_modules[目录] // 项目使用的包目录,开发使用和上线使用的都在里边
+-- src[目录] // 源文件/代码,程序员主要编写的目录
| +-- app.controller.spec.ts // 对于基本控制器的单元测试样例
| +-- app.controller.ts // 控制器文件,可以简单理解为路由文件
| +-- app.module.ts // 模块文件,在NestJS世界里主要操作的就是模块
| +-- app.service.ts // 服务文件,提供的服务文件,业务逻辑编写在这里
| +-- app.main.ts // 项目的入口文件,里边包括项目的主模块和监听端口号
+-- test[目录] // 测试文件目录,对项目测试时使用的目录,比如单元测试...
| +-- app.e2e-spec.ts // e2e测试,端对端测试文件,测试流程和功能使用
| +-- jest-e2e.json // jest测试文件,jset是一款简介的JavaScript测试框架
+-- .eslintrc.js // ESlint的配置文件
+-- .gitignore // git的配置文件,用于控制哪些文件不受Git管理
+-- .prettierrc // prettier配置文件,用于美化/格式化代码的
+-- nest-cli.json // 整个项目的配置文件,这个需要根据项目进行不同的配置
+-- package-lock.json // 防止由于包不同,导致项目无法启动的配置文件,固定包版本
+-- package.json // 项目依赖包管理文件和Script文件,比如如何启动项目的命令
+-- README.md // 对项目的描述文件,markdown语法
+-- tsconfig.build.json // TypeScript语法构建时的配置文件
+-- tsconfig.json // TypeScript的配置文件,控制TypeScript编译器的一些行为
五、Controller控制器-路由的创建
5.1、创建请求地址
创建 http://localhost:3000/name 的请求地址(接口地址)
src/service.ts
// 服务文件,提供的服务文件,业务逻辑编写在这里
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World Snow!';
}
getName(): string {
return 'SNOW!';
}
}
src/controller.ts
// 控制器--编写路由
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller('api') // 添加顶层路径 api
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
@Get('name')
getName(): string {
return this.appService.getName();
}
}
访问成功。
5.2、添加顶层路径 api
访问成功 api/name
5.3、src下创建product模块
5.3.1、删除以下文件
5.3.2、app.module.ts删除对应的使用
5.3.3、新建module
nest g module products
5.3.4、创建controller
nest g controller products --no-spec
src/products/products.controller.ts
import { Controller, Get } from '@nestjs/common';
@Controller('products')
export class ProductsController {
@Get()
getProductsList(): any{
return {
code: 0,
data: ['huawei', 'changcheng', 'biyadi'],
msg: '请求产品列表成功'
}
}
}
5.4、src/main.ts 设置默认前缀 api/
app.setGlobalPrefix('api/')
六、Controller控制器-使用products.service.ts写业务逻辑
6.1、把业务逻辑放在products.service.ts这个文件中。nestjs规范。
nest g service products --no-spec
6.2、src/products/products.controller.ts 引入 service
import { ProductsService } from './products.service';
import { Controller, Get } from '@nestjs/common';
import { ProductsService } from './products.service';
@Controller('products')
export class ProductsController {
// this.productsService = new ProductsService() 等价于 constructor 方式
constructor(private productsService: ProductsService){}
@Get()
getProductsList(): any{
return this.productsService.getProductsList()
}
}
6.3、src/products/products.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class ProductsService {
getProductsList(){
return {
code: 0,
data: ['huawei', 'changcheng', 'biyadi'],
msg: '请求产品列表成功'
}
}
}
七、Controller控制器 Get 请求
7.1、get请求 -- 带参数
src/products/products.controller.ts
@Get('/getProductsById')
// @Request()装饰器
// getProductsById(@Request() req):any{
// let id:number = parseInt(req.query.id)
// return this.productsService.getProductsById(id)
// }
// @Query()装饰器
getProductsById(@Query() query):any{
let id:number = parseInt(query.id)
return this.productsService.getProductsById(id)
}
src/products/products.service.ts
getProductsById(id:number){
let resJson:any = {}
switch (id) {
case 1:
resJson = {id:1, name: 'huawei', type: 'shouji'}
break;
case 2:
resJson = {id:2, name: 'changcheng', type: 'qiche'}
break;
case 3:
resJson = {id:3, name: 'biyadi', type: 'qiche'}
break;
}
return resJson;
}
RESTClient/demo.http
7.2、Get请求-@Request()装饰器-动态参数id
src/products/products.controller.ts
// Get请求-@Request()装饰器-动态参数id
@Get('/getProductsByIdRouter/:id')
getProductsByIdRouter(@Request() req):any{
console.log()
let id:number = parseInt(req.params.id)
return this.productsService.getProductsByIdRouter(id)
}
src/products/products.service.ts
getProductsByIdRouter(id:number){
let resJson:any = {}
switch (id) {
case 1:
resJson = {id:1, name: 'huawei', type: 'shouji'}
break;
case 2:
resJson = {id:2, name: 'changcheng', type: 'qiche'}
break;
case 3:
resJson = {id:3, name: 'biyadi', type: 'qiche'}
break;
}
return resJson;
}
RESTClient/demo.http
http://localhost:3000/api/products/getProductsByIdRouter/1 HTTP/1.1
7.3、Get请求-@Param()装饰器-动态参数id,name
src/products/products.controller.ts
// Get请求-@Param()装饰器-动态参数id,name
@Get('/getProductsByIdRouter/:id/:name')
getProductsByIdRouter2(@Param() Params):any{
console.log()
let id:number = parseInt(Params.id)
let name:string = Params.name
return this.productsService.getProductsByIdRouter2(id, name)
}
src/products/products.service.ts
getProductsByIdRouter2(id:number, name:string = "huawei"){
let resJson:any = {}
switch (id) {
case 1:
resJson = {id:1, name: name, type: 'shouji'}
break;
case 2:
resJson = {id:2, name: name, type: 'qiche'}
break;
case 3:
resJson = {id:3, name: name, type: 'qiche'}
break;
}
return resJson;
}
RESTClient/demo.http
http://localhost:3000/api/products/getProductsByIdRouter/1/huawei-mate-60 HTTP/1.1
八、Controller控制器 Post 请求
8.1、post请求
src/products/products.controller.ts
@Post('/addProducts')
addProducts(): any{
return this.productsService.addProducts()
}
src/products/products.service.ts
addProducts(){
return {
code: 200,
data: ['huawei', 'changcheng', 'biyadi'],
msg: '增加产品成功'
}
}
8.2、post请求 -- 带参数
src/products/products.controller.ts
// @Query()装饰器
getProductsById(@Query() query):any{
let id:number = parseInt(query.id)
return this.productsService.getProductsById(id)
}
src/products/products.service.ts
addProducts2(id: any){
console.log(id)
let resJson:any = {
code: 200,
data: ['huawei', 'changcheng', 'biyadi'],
msg: '增加产品成功'
}
switch (id) {
case 1:
resJson.data = ['huawei']
break;
case 2:
resJson.data = ['changcheng']
break;
case 3:
resJson.data = ['biyadi']
break;
}
return resJson
}
RESTClient/demo.http
POST http://localhost:3000/api/products/addProducts2
Content-Type: application/json
{
"id": 1
}
九、TypeORM 连接mysql数据库,增删改查
十、其他内容待更新
过程记录
记录一、nestjs热更新
nestjs自带nodemon可以热更新,启动方式npm run start:dev(package.json里)
记录二、使用VsCode插件 REST Client
项目根目录创建RESTClient目录,demo.http文件
POST 接口地址 HTTP/1.1 点击Send Request 请求结果如右图
记录三、
Content-Type 和 json字符串中间必须有一个空行 url和conten-type之间不能有空行
增加空行后即可