《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项目实战 等相关文章,敬请期待~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/711843.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

cs与msf权限传递,以及mimikatz抓取明文密码

cs与msf权限传递&#xff0c;以及mimikatz抓取win10明文密码 1、环境准备2、Cobalt Strike ------> MSF2.1 Cobalt Strike拿权限2.2 将CS权限传递给msf 3、MSF ------> Cobalt Strike3.1 msf拿权限3.2 将msf权限传递给CS 4、使用mimikatz抓取明文密码 1、环境准备 攻击&…

使用libpurple函数库接入服务器

代码; #define CUSTOM_USER_DIRECTORY "/dev/null" // 定义用户目录 #define CUSTOM_PLUGIN_PATH "" // 定义插件目录 #define PLUGIN_SAVE_PREF "/purple/nullclient/plugins/saved" // 定义插件头目录 #define UI_ID "nullc…

如何实现电脑监视员工的电脑屏幕?六个方法偷偷分享给你

实现电脑监视员工的电脑屏幕&#xff0c;通常需要借助专业的监控软件或系统&#xff0c;这些工具旨在帮助企业管理者监督员工的工作状态&#xff0c;确保工作效率&#xff0c;同时保护公司资产和数据安全。以下是几种常见的实现方式。 1. 使用专业的远程监控软件 安企神软件&a…

如何进行LLM大模型推理优化

解密LLM大模型推理优化本质 一、LLM推理的本质以及考量点 LLM推理聚焦Transformer架构的Decoder以生成文本。过程分两步&#xff1a;首先&#xff0c;模型初始化并加载输入文本&#xff1b;接着&#xff0c;进入解码阶段&#xff0c;模型自回归地生成文本&#xff0c;直至满足…

微服务feign组件学习

手写不易&#xff0c;对您有帮助。麻烦一键三连。也欢饮各位大料指正&#xff0c;交流。 微服务feign组件学习 1.概念1.1 feign 概念1.2 Ribbon概念 2.使用2.1 集成feign2.1.1 maven依赖2.1.2 项目结构 2.2 使用2.2.1 定义feign接口2.2.2 消费端服务调用2.2.3 消费端扫描feig…

基于scikit-learn的机器学习分类任务实践——集成学习

一、传统机器学习分类流程与经典思想算法简述 传统机器学习是指&#xff0c;利用线性代数、数理统计与优化算法等数学方式从设计获取的数据集中构建预测学习器&#xff0c;进而对未知数据分类或回归。其主要流程大致可分为七个部分&#xff0c;依次为设计获取数据特征集&#x…

20240615给飞凌的OK3588-C开发板刷Rockchip原厂的Buildroot后的测试报告

20240615给飞凌的OK3588-C开发板刷Rockchip原厂的Buildroot后的测试报告&#xff1a; 【切记&#xff0c;由于没有替换DTS的&#xff0c;开发板发热量巨大&#xff01;因此配备鼓风机进行加强散热了】 0、adb 默认没有 1、HDMI IN 4K 2024/6/15 20:32 4K全屏 2、HDMI OUT …

博客论坛系统java博客管理系统基于springboot+vue的前后端分离博客论坛系统

文章目录 博客论坛系统一、项目演示二、项目介绍三、部分功能截图四、部分代码展示五、底部获取项目源码&#xff08;9.9&#xffe5;带走&#xff09; 博客论坛系统 一、项目演示 博客论坛系统 二、项目介绍 基于springbootvue的前后端分离博客论坛系统 系统角色&#xff1a…

【Arthas案例】某应用依赖两个GAV不同但包含两个相同全限定类名StaticLoggerBinder,引起log4j.Level类找不到异常

3分钟内解决问题 两个不同的GAV依赖冲突&#xff0c;包含相同全限定类名&#xff0c;引起ClassNotFoundException Maven依赖的三坐标体系GAV(G-groupId&#xff0c;A-artifactId&#xff0c;V-version) 【案例1】某应用依赖两个GAV不同的jar&#xff0c;但包含两个相同全限定类…

虚函数机制-动态绑定的应用

虚函数使得程序在运行的时候根据指针指向对象的类型来确定调用哪个函数。 下图中&#xff1a;都为静态绑定。因为在编译器就确定了可以调用的函数 此时当基类指针指向派生类对象时&#xff0c;因为没有virtual关键字&#xff0c;所以在编译阶段就根据指针类型确定了要指向的函…

MEMS:Lecture 17 Noise MDS

讲义 Minimum Detectable Signal (MDS) Minimum Detectable Signal&#xff08;最小可检测信号&#xff09;是指当信号-噪声比&#xff08;Signal-to-Noise Ratio, SNR&#xff09;等于1时的输入信号水平。简单来说&#xff0c;MDS 是一个系统能够分辨出信号存在的最低输入信号…

Tomcat基础详解

第一篇&#xff1a;Tomcat基础篇 lecture&#xff1a;邓澎波 一、构建Tomcat源码环境 工欲善其事必先利其器&#xff0c;为了学好Tomcat源码&#xff0c;我们需要先在本地构建一个Tomcat的运行环境。 1.源码环境下载 源码有两种下载方式&#xff1a; 1.1 官网下载 https://…

matplotlib twinx多y轴但单个图例

matplotlib 用 twinx 画多 y 轴参考 [1]。现想在画图例时&#xff0c;多个 y 轴的图例画在一起&#xff0c;写法参考 [2]。本文展示一个简例&#xff0c;效果&#xff1a; Code 要手动指定颜色&#xff0c;否则原 y 轴的用色和新 y 轴会重合。 import matplotlib.pyplot as…

基于SVD的点云配准(下)

点云配准及特征提取详细解读 本篇博客将介绍一个用于点云配准的 C++ 代码示例,该示例使用 PCL(Point Cloud Library)库来处理和配准两个点云数据集。我们将逐步解析代码的关键部分,并解释每个步骤的作用。 代码说明 代码的整体结构及其主要功能: int main(int argc, ch…

VRChat 2024年裁员原因与背景深度分析

VRChat&#xff0c;作为2022年元宇宙/VR社交领域的巨头&#xff0c;近期在2024年宣布裁员计划&#xff0c;其背后原因和背景值得业界尤其是仍在纯元宇宙虚拟空间创业的同仁们重点关注。 一、创始人决策失误 根据CEO的邮件披露&#xff0c;VRChat的创始人因缺乏经验和过度自信…

Vue基本使用-02

上节我们讲了什么是mvvm模型&#xff0c;以及我们vue的一些常用指令&#xff0c;今天给大家讲一下vue的基本使用&#xff0c;在将之前我们需要重点讲解我们的一个指令&#xff0c;v-model指令 v-model v-model 可以在组件上使用以实现双向绑定,什么是双向绑定呢?意思就是当我们…

[C#]使用C#部署yolov10的目标检测tensorrt模型

【测试通过环境】 win10 x64vs2019 cuda11.7cudnn8.8.0 TensorRT-8.6.1.6 opencvsharp4.9.0 .NET Framework4.7.2 NVIDIA GeForce RTX 2070 Super cuda和tensorrt版本和上述环境版本不一样的需要重新编译TensorRtExtern.dll&#xff0c;TensorRtExtern源码地址&#xff1a;T…

IP地址、子网掩码、网段、网关

前面相同就是在同一个网段 如果子网掩码和网络号相与的结果是一样的&#xff0c;那么他们就在同一个子网 IP地址、子网掩码、网络号、主机号、网络地址、主机地址以及ip段/数字-如192.168.0.1/24是什么意思?_掩码248可以用几个ip-CSDN博客

第九届星华杯网络邀请赛

T1喵星人的身高 T2犇犇碑 T3嘤嘤词典 T4三角区间和

REST风格

黑马程序员Spring Boot2 文章目录 1、REST简介1.1 优点1.2 REST风格简介1.3 注意事项 2、RESTful入门案例 1、REST简介 1.1 优点 隐藏资源的访问行为&#xff0c;无法通过地址的值对资源适合中操作书写简化 1.2 REST风格简介 按照RST风格访问资源时使用行为动作区分对资源进…