《Nest系列 - 1. 运行一个Nest项目以及整体目录学习》

2024-06-14 17:04

本文主要是介绍《Nest系列 - 1. 运行一个Nest项目以及整体目录学习》,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

初识Nest心路历程

作为一名前端开发,说实话,学习Nest后端技术, 会有一定的成本。我试着阅读文档,安装项目,把项目跑起来,

当我看到久违的Hellow world 后,还来不及欣喜,就困惑了, 作为一个后端框架,数据不是都会在浏览器 NetWork里看返回的数据,这怎么还直接显示在页面了

image.png

image.png

这让我对 MVC的理解,又有点模糊了 。

当我正要查看代码,发现和vue项目的整体结构还差不多,但是当我打开具体的目录,又懵逼了,@Controller(), @Get(), @Module 这都什么玩意,当我再起看文档

依赖注入,控制反转,装饰器,中间件,管道 看到这些名词,就已经把我劝退了。

image.png

当我再看到 模块,中间件,异常过滤器,守卫,拦截器 又感觉还能学,这不就是模块,axios请求,拦截,路由守卫那一部分的知识。

终于当我历经几天的犹豫,决定入坑Nest后端框架,下面就让我们开始学习Nest系列文章

项目脚手架 安装

使用脚手架Nest CLI 构建项目

// 安装全局@nestjs/cli
1. npm i -g @nestjs/cli// 创建一个nest项目
2. nest new project-name// 运行项目
3. pnpm run start:dev

选择一个包管理工具,静待安装完毕

image.png

运行项目

image.png

image.png

项目目录说明

+-- 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编译器的一些行为  

src目录下的文件说明

src目录是日常工作编写代码的主要目录,从基本的目录结构也可以对NestJS编写模式有很好的了解。

+-- src[目录]                       // 源文件/代码,程序员主要编写的目录
|  +-- app.controller.spec.ts      // 对于基本控制器的单元测试样例
|  +-- app.controller.ts           // 控制器文件,可以简单理解为路由文件
|  +-- app.module.ts               // 模块文件,在NestJS世界里主要操作的就是模块
|  +-- app.service.ts              // 服务文件,提供的服务文件,业务逻辑编写在这里
|  +-- app.main.ts                 // 项目的入口文件,里边包括项目的主模块和监听端口号

细节的东西不用关心太多,我们需要先把整个项目的架构,大体运行机制搞明白,才能进行下面细致入微的学习

1. 从app.main.ts 入口文件开始看起

image.png

  • 通过 @nestjs/core 导入 NestFactory

  • 主要作用是Use NestFactory to create an application instance 使用NestFactory创建应用程序实例

  • 然后使用实例设置监听端口

这就跟我们在 vue 中一样,创建一个实例

 import { createApp } from 'vue'import App from './App.vue'const app = createApp(App)

我们是把html 文件中的 <div id="app"></div>挂载到 实例上 app.mount(‘#app’)

而在Nest 中,是把AppModule(模块),挂载到实例上。

2. 那具体AppModule 是什么呢?

image.png

AppModule这个类 啥也没干,就导出了? export class AppModule {}

image.png

其实不然,这里遇到了第一个新的概念: 装饰器

@Module - 当类被 module 装饰器装饰的时候,它就是一个模块。从代码层面来看,这个模块的作用就是组合AppController 和 AppService ,把他们聚合在一起,供 AppModule 使用

  1. AppController 是什么呢?

image.png

这个实例并不明显,因为没有体现出他的路由作用,那要是我这样写,你或许就明白了

image.png

@Get('index') 就是请求方法类型, 参数是路径/参数
在里面调用了 appService.getHello 的方法 来返回具体的结果

从前端的角度来看Nest的执行顺序

我们请求一个接口 大致流程 是这样的 传递路径/参数 服务端返回对应的结果


axios.get('/user?ID=12345').then(function (response) {console.log(response);}).catch(function (error) {console.log(error);});

服务端,在 controller 层会对路由做一个匹配 匹配到响应的路由,service 去做业务逻辑/和数据库交互

疑问点答疑

1. 全篇都是export class ,怎么没见new 实例化调用呢?

在 NestJS 中,大部分组件(如控制器、服务、模块等)都是通过 class 来定义的,而且通常不需要显式地使用 new 关键字来实例化这些组件。这是因为 NestJS 基于依赖注入(Dependency Injection)的设计理念,在运行时由 NestJS 框架负责创建和管理组件的实例。

这也是我在学Nest最大的一个疑惑,也是Nest中比较伟大的一个设计,@Injectable,@Controller,下面跟了一个class ,就代表这个class 是可以被注入的,换句话说,就是这个class ,我Nest 会自动帮你进行 new 操作,你直接调用里面的方法举行

@Controller()
export class AppController {constructor(private readonly appService: AppService) {}@Get()getHello(): string {return this.appService.getHello(); // AppService 这个类,没有new,就可以直接使用实例上的方法,是因为她是可以被注入的,也就是有@Inject,Nest 会自动帮我们注入到AppController中}
}
依赖注入(Dependency Injection)

依赖注入是一种设计模式,通过它,类的依赖关系可以在运行时动态地注入到类中而不是在类内部直接创建依赖的实例。在 NestJS 中,组件之间的依赖关系通过依赖注入实现,这样可以更好地解耦组件之间的关系,提高代码的可测试性和可维护性。

举个例子,当你在一个 NestJS 控制器的构造函数中声明一个服务作为参数时,NestJS 框架会自动注入该服务的实例,而不需要手动创建。例如:

typescriptCopy Code
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';@Controller('users')
export class UserController {
// 注入的方式可以是构造器注入:constructor(private readonly appService: AppService) {}
// 或者属性注入:
// @Inject(AppService)
// private readonly appService: AppService@Get()findAll(): string {return this.appService.findAll();}
}

在上面的例子中,AppService 被声明为 UserController 的构造函数的参数,通过 TypeScript 的语法,private readonly appService: AppService 相当于声明了一个私有成员变量,并将传入的 AppService 实例赋给了这个成员变量。NestJS 框架在初始化 UserController 时,会自动创建并注入 AppService 的实例。

这种方式使得代码更加简洁,同时也减少了对全局状态的依赖,使得组件更容易被复用和测试。

因此,在 NestJS 中,通常不需要手动使用 new 关键字来实例化,框架会在需要的时候自动处理组件的创建和注入。

这个和前端模块很相似,模块有导出,就有导入,才能使用。而 在Nest中,模块导出,需要导入并且使用new 去实例化类,但是不是通过new 来实例化,而是通过依赖注入的方式去实例化,并且后续调用实例上的方法

总结

  1. 可以使用cli快速搭建项目,并且运行项目
  2. 对每个目录进行分析,掌握整体项目结构
  3. 从app.main.ts 出来,开始 逐步分析,通过NestFactory创建一个实例,然后把模块传入
  4. 模块就是一个集合,里面聚合了Controller,Service
  5. Controller 就是一个控制器文件,可以简单理解为路由文件,里面会设置请求方法/请求参数, 然后调用Service 类 来做业务逻辑处理/和数据库交互
  6. 这么多的class ,都不需要new 去实例化调用,而且调用关系/调用顺序怎么处理,最主要的是利用了依赖注入这个设计模式,类的依赖关系可以在运行时动态地注入到类中,而不是在类内部直接创建依赖的实例。
  7. 依赖注入可以是构造器注入,也可以是属性注入,相比构造器注入更简便,但是属性注入易读性更强
  8. 只要是类,只要被装饰器修饰,类的依赖关系可以在运行时动态地注入到类中,而不是在类内部直接创建依赖的实例

后记

后面会陆续完成装饰器/CURD/ 中间件/日志/api 文档/Nest项目实战 等相关文章,敬请期待~~~

这篇关于《Nest系列 - 1. 运行一个Nest项目以及整体目录学习》的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1061001

相关文章

部署Vue项目到服务器后404错误的原因及解决方案

《部署Vue项目到服务器后404错误的原因及解决方案》文章介绍了Vue项目部署步骤以及404错误的解决方案,部署步骤包括构建项目、上传文件、配置Web服务器、重启Nginx和访问域名,404错误通常是... 目录一、vue项目部署步骤二、404错误原因及解决方案错误场景原因分析解决方案一、Vue项目部署步骤

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

配置springboot项目动静分离打包分离lib方式

《配置springboot项目动静分离打包分离lib方式》本文介绍了如何将SpringBoot工程中的静态资源和配置文件分离出来,以减少jar包大小,方便修改配置文件,通过在jar包同级目录创建co... 目录前言1、分离配置文件原理2、pom文件配置3、使用package命令打包4、总结前言默认情况下,

python实现简易SSL的项目实践

《python实现简易SSL的项目实践》本文主要介绍了python实现简易SSL的项目实践,包括CA.py、server.py和client.py三个模块,文中通过示例代码介绍的非常详细,对大家的学习... 目录运行环境运行前准备程序实现与流程说明运行截图代码CA.pyclient.pyserver.py参

通过prometheus监控Tomcat运行状态的操作流程

《通过prometheus监控Tomcat运行状态的操作流程》文章介绍了如何安装和配置Tomcat,并使用Prometheus和TomcatExporter来监控Tomcat的运行状态,文章详细讲解了... 目录Tomcat安装配置以及prometheus监控Tomcat一. 安装并配置tomcat1、安装

mysqld_multi在Linux服务器上运行多个MySQL实例

《mysqld_multi在Linux服务器上运行多个MySQL实例》在Linux系统上使用mysqld_multi来启动和管理多个MySQL实例是一种常见的做法,这种方式允许你在同一台机器上运行多个... 目录1. 安装mysql2. 配置文件示例配置文件3. 创建数据目录4. 启动和管理实例启动所有实例

IDEA运行spring项目时,控制台未出现的解决方案

《IDEA运行spring项目时,控制台未出现的解决方案》文章总结了在使用IDEA运行代码时,控制台未出现的问题和解决方案,问题可能是由于点击图标或重启IDEA后控制台仍未显示,解决方案提供了解决方法... 目录问题分析解决方案总结问题js使用IDEA,点击运行按钮,运行结束,但控制台未出现http://

解决Spring运行时报错:Consider defining a bean of type ‘xxx.xxx.xxx.Xxx‘ in your configuration

《解决Spring运行时报错:Considerdefiningabeanoftype‘xxx.xxx.xxx.Xxx‘inyourconfiguration》该文章主要讲述了在使用S... 目录问题分析解决方案总结问题Description:Parameter 0 of constructor in x

解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题

《解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题》文章详细描述了在使用lombok的@Data注解标注实体类时遇到编译无误但运行时报错的问题,分析... 目录问题分析问题解决方案步骤一步骤二步骤三总结问题使用lombok注解@Data标注实体类,编译时