NestJS(1)初识 NestJS 和 Hello, World

news2024/9/20 14:31:56

初识 NestJS

先来看下官网对 NestJS 的介绍。

Nest (NestJS) 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的开发框架。它利用 JavaScript 的渐进增强的能力,使用并完全支持 TypeScript (仍然允许开发者使用纯 JavaScript 进行开发),并结合了 OOP (面向对象编程)、FP (函数式编程)和 FRP (函数响应式编程)。

在底层,Nest 构建在强大的 HTTP 服务器框架上,例如 Express (默认),并且还可以通过配置从而使用 Fastify !

Nest 在这些常见的 Node.js 框架 (Express/Fastify) 之上提高了一个抽象级别,但仍然向开发者直接暴露了底层框架的 API。这使得开发者可以自由地使用适用于底层平台的无数的第三方模块。

通过这段文字,可知道以下几点:

  1. NestJS 是一个基于 Node.js 的服务端应用开发框架
  2. 完全支持 TypeScript,也可以使用纯 JS 开发
  3. 支持多种编程范式,例如 OOP 和 FR
  4. 底层处理 HTTP 请求,还是使用了 Express(默认),也可切换为 Fastify
  5. 有无数的第三方模块可供使用

下面就开始上手 NestJS 应用的开发吧。

快速初始化

Nestjs 官方提供了一个很好用的脚手架工具,可以用来快速创建,开发和构建一个 Nestjs 应用。

首先全局安装脚手架工具:

npm install -g @nestjs/cli

查看脚手架版本号:

nest -v
9.1.8

使用脚手架提供的 new 命令创建项目:

nest new hello-nest

命令行中会提示选择一个你想要的包管理工具,本文使用 Pnpm :

image-20230113172003243

脚手架工具创建了很多文件,然后安装依赖中:

image-20230113172025874

稍等片刻,这是项目项目初始化完成后的样子:

image-20230113172043299

根据提示,进入项目目录,执行启动命令,即可运行一个 Nestjs 应用了:

$ cd hello-nest
$ pnpm run start

image-20230114143246000

在命令行窗口中,有一些打印的信息,我们可以简单看一下。

> hello-nest@0.0.1 start D:\2023code\hello-nest
这一行是项目的名字以及版本号,和项目所在路径

> nest start
这一行是启动项目的命令

下面是应用运行的日志信息
[Nest] 42416  - 2023/01/14 14:32:29     LOG [NestFactory] Starting Nest application...
NestFactory(Nest 工厂类)日志,启动了 Nest 应用

[Nest] 42416  - 2023/01/14 14:32:29     LOG [InstanceLoader] AppModule dependencies initialized +24ms
InstanceLoader(实例加载器类) 日志,App 模块的依赖完成初始化

[Nest] 42416  - 2023/01/14 14:32:29     LOG [RoutesResolver] AppController {/}: +5ms
RoutesResolver(路由解析器类) 日志,App 控制器建立了 ‘/’ 这个路由    

[Nest] 42416  - 2023/01/14 14:32:29     LOG [RouterExplorer] Mapped {/, GET} route +2ms
RouterExplorer(路由管理器类) 日志,完成了 'GET /' 路由的映射

[Nest] 42416  - 2023/01/14 14:32:29     LOG [NestApplication] Nest application successfully started +1ms
NestApplication(Nest 应用程序类) 日志,Nest 应用成功启动

所以现在,浏览器就可以访问/ 这个路由了。

Hello, world

Nest 应用默认的端口是 3000,打开浏览器,访问 localhost:3000,就可以看到如下界面:

image-20230114144932740

接下来我们去看下源码,看下 NestJS 是如何将这个 Hello, World 响应给浏览器的。

分析 Hello, World

下面是刚刚所创建的 Nest 项目的目录结构。

image-20230114150635459

我们先来关注下 src 目录,它下面有五个 .ts 文件,分别是:

  • app.controller.spec.ts:App 控制器的单元测试文件

  • app.controller.ts:App 模块的控制器

  • app.module.ts:App 模块,也是 Nest 应用的根模块

  • app.service.ts:App 模块的服务层代码

  • main.ts:Nest 应用入口文件,用来创建 Nest 应用实例和启动应用

从 main.ts 看起

打开 src/main.ts,这是 Nest 应用的入口文件。代码很简单:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();

该文件封装了一个 bootstrap 函数,用于创建 Nest 应用。内部调用 NestFactory 工厂类的 create 方法,将 AppModule 传入,创建应用实例。最后应用调用 listen 方法,监听 3000 端口,完成 web 服务的启动。

如果你写过 Vue ,可以将此文件和 Vue 项目的入口文件 main.js做一个类比。NestFactory.create 好比是 createApp 方法,AppModule 模块好比是 App.vue根组件。如果你使用 Express 或者 Koa,listen 方法更不用多说,可以类比为组件的挂载 mount 方法,它是创建应用的最后一步。

app.module.ts

Nest 应用是以模块 Module 为单元的。模块有两个核心成员,控制器提供者。可以将模块理解为前端 Vue 项目中的组件main.ts 导出一个 AppModule 类,是 Nest 应用的根模块,就好比是 Vue 应用中的根组件。

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

在该文件中,导入了 App 模块的控制器 AppController服务 AppService,然后通过装饰器(类似于 Java 中的注解) @Module,将 AppModule 类声明为一个模块。

装饰器 @Module 接收了几个属性, controllersproviders。前者接收控制器,后者接收提供者,Nest 中提供者有很多中,代码中的 AppService 是提供者的一种。通过装饰器和这两个属性,一个模块就能将控制器和服务组织到一起

app.controller.ts

这是 App 模块的控制器层代码,用来接收用户请求,调用服务层处理后,再将结果返回给客户端。

import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}

它首先导入了 Nestjs 核心包提供的两个装饰器,然后导入了 App 模块的服务类。通过 @Controller 装饰器,将 AppController 类声明为一个控制器。代码中类的构造方法是一种简写模式,作用是将 AppService 服务类的实例挂载到了控制器的实例上,并且还是私有成员,用伪代码表示就是:

class AppController {
    constructor() {
        this.appService = new AppService()
    }
}

但是实际上 AppService 服务类并不是在这里实例化的,而是作为依赖交给依赖注入容器的去管理的。

所以在类的成员方法中就可以直接调用 this.appService了。

然后又使用了 @Get 装饰器声明了 getHello 方法,表示此方法用于处理 HHTPGET请求。@Controller@Get 都可以接收字符串类型的参数用来拼接路由,比如 @Controller('news')@Get('list'),拼接出来的路由就是 /news/list。示例代码中装饰器都省略了参数,默认为空字符串,所对应的路由就是根路由 /。就好比 Express 中:

app.get('/', getHello)
app.get('/news/list', getNewsList)

getHello 方法内部调用了 App 服务层的 getHello 方法,所以接下来就该去看看 app.service.ts 了。

app.service.ts

这是 AppModule 的服务层文件,也是真正处理业务的地方。

import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World!';
  }
}

该文件导入了一个 @Injectable 装饰器,它将 AppService 类型声明为了“提供者”。Nest 中有很多种提供者,这里的“服务”就是一种最常用的提供者。这里涉及到依赖注入的概念,提供者在依赖注入中的角色就是就是可以被注入到容器中的类。

这段代码可以先简单理解为使用了这个装饰器之后,AppService 类的实例可以直接在控制器中使用,而无需手动导入和实例化

AppService 类有一个 getHello 方法,返回 Hello, World! 字符串,这就是我们在浏览器中看到的那个。它返回的字符串,交给了 App 控制器,控制器又返回给了浏览器,至此,一个完整的流程就走完了。

nest 应用逻辑流程

总结

本文介绍了使用 @nest/cli 脚手架快速创建和启动一个 Nest 应用,随后又对“Hello, World”示例代码做了分析,简单介绍了一些 TypeSscript 语法,比如装饰器,和一些 Nest 的概念。相信看到这里,大家基本上了解了 Nest 应用接收到用户请求后,走了哪些流程,完成了响应。

我们下篇文章见。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

YARN On Mapreduce搭建与wordCount案例实现

文章目录 1.前言1.YARN 集群搭建1.1 ResourceManager High Availability 架构图1.2 配置文件mapred-site.xmlyarn-site.xml 1.3 启动服务和rm启动yarn启动rm资源管理访问页面查看集群状态 2.运行官方的WC案例2.1 运行jar准备一个data.txt文件日志查看输出 1.前言 YARN的基本思…

JVM原理

JVM 什么是JVM? JVM是一种虚拟出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。 JVM有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。Java语言最重要的特点就是跨平台运行。 使用J…

Nginx之rewrite与location重写功能

一、常用的Nginx 正则表达式 字符涵义以及示例^匹配输入字符串的起始位置$匹配输入字符串的结束位置*匹配前面的字符零次或多次;如“ol*”能匹配“o”及“ol”、“oll”匹配前面的字符一次或多次;如“ol”能匹配“ol”及“oll”、“olll”,但…

GoJS Beginner Tutorial #1

1.关系图: gojs部件由一个或多个gojs面板组成,这些面板包含和组织各种gojs图形对象 通常使用go.GraphObject.make创建一个GraphObject,我们通过使用$符号变量缩短了该函数的名称 这个函数的第一个参数,往往是你想要制作的GraphOb…

Sentinel同时配置fallback和blockHandler的问题

Spring Cloud在使用Sentinel进行服务降级和熔断时,如果同时配置了fallback和blockHandler,则在服务熔断后,抛出的BlockException不会再fallback逻辑中执行,而是在blockHandler逻辑中执行。 首先来看只配置了fallback的情况&#x…

Python文件管理【open和with open的使用】

一、文件的操作步骤 基本都是三个步骤: 打开文件、读写文件、关闭文件 1.open()函数 在python,使用open函数,可以打开一个已经存在的文件,或者创建一个新的文件,语法如下: open(name,mode) name&#xff…

LeafLet加载自定义Legend的设计与实现

背景 众所周知,在GIS的世界里,图例和地图永远是一对一起出现的对象。在地图上表示地理环境各要素,比如山脉、河流、城市、铁路等所用的符号叫做图例。这些符号所表示的意义,常注明在地图的边角上。图例是表达地图内容的基本形式和…

引用与指针:在C++中如何做出正确的选择?

文章目录 前言1. 引用入门2. 引用作为函数传参3. 引用作为函数返回值4. 引用和指针5. 其他区别 前言 引用是 C 的新增内容,在实际开发中会经常使用,它就如同C语言的指针一样重要,但它比指针更加方便和易用,有时候甚至是不可或缺的…

使用YOLOV5-6.2预训练模型(yolov5s)进行detect的详细说明(detect.py)文件解析

目录 准备源文件和预训练文件下载python版本以及torch版本说明:文件目录说明测试文件 detect.py使用测试单张图片测试一个文件夹里的图片 准备 源文件和预训练文件下载 下载链接:https://github.com/ultralytics/yolov5/releases/tag/v6.2 源文件和预训…

数据科学与机器学习在软件开发中的应用

数据科学和机器学习是现代软件开发的重要组成部分,可以帮助开发人员更好地理解和分析数据,从而提高软件的质量和性能。在本篇博客中,我将深入探讨数据科学和机器学习在软件开发中的应用,并讨论它们如何帮助我们创建更好的软件。 …

你最想知道的APP自动化测试项目实战详解

目录 一、引言 二、APP自动化测试的基本概念 三、APP自动化测试的流程 四、APP自动化测试的最佳实践 五、常见的APP自动化测试工具 六、APP自动化测试的挑战和解决方案 七、结论 一、引言 随着移动设备的普及和应用市场的繁荣,越来越多的企业开始开发和发布移…

【手撕MyBatis源码】执行器与缓存

文章目录 概述执行器(Executor)执行器总结 缓存MyBatis缓存概述一级缓存(LocalCache)Spring集成MyBatis后一级缓存失效的问题二级缓存二级缓存组件结构二级缓存的使用为什么要提交之后才能命中二级缓存?二级缓存结构二级缓存执行流程 概述 通过一条修改语句,我们来…

Android 开发死磕性能优化,方向是否正确?

在 Android 开发者技能中,如果想进大厂,一般拥有较好的学历可能有优势一些。 但是如果你靠硬实力也是有机会的,例如死磕性能优化,成为一名Android性能优化的高手,也算是目前招聘过程中比较稀缺的人才,可以…

Maven安装及其原理

一、maven安装 maven 3.6.1的安装包如下 二、配置本地仓库和阿里云私服 打开在上述百度网盘下载的文件,打开conf下面的setting.xml,大概第55行增加如下代码 ,意思是指定一个目录为本地jar包的文件夹,管理jar包。一般来说&…

C++位图

位图 文章目录 位图setResetTest整体代码位图应用 给定40亿个不重复、没排序的无符号整数,再给一个无符号整数,如何快速判断一个数是否在这40亿个数中???首先想到的是归并排序二分查找。排序可以排,但是通过…

【计算机组成原理】第三章 存储系统

文章目录 知识体系3.1 存储器概述3.1.1 存储器的分类3.1.2 存储器的性能指标3.1.3 多级层次的存储系统 3.2 主存储器3.2.1 SRAM芯片和DRAM芯片3.2.2 只读存储器3.2.3 主存储器的基本组成3.2.4 多模块存储器 3.3 主存储器与CPU的连接3.3.1 连接原理3.3.2 主存容量的扩展3.3.3 存…

指定GPU运行python程序

一、命令行运行python程序时 1、首先查看哪些GPU空闲,nvidia-smi显示当前GPU使用情况。 nvidia-smiGPU:编号,这里是0和1 Fan:风扇转速,在0到100%之间变动,第一个是29% Name:显卡名&#xff…

布署到centos7.9时,ModuleNotFoundError: No module named ‘_sqlite3‘

先下载编译sqlite3 wget http://www.sqlite.org/sqlite-3.5.6.tar.gz cd sqlite-3.5.6 ./configure --disable-tcl make && make install 注意add LIBDIR to the ‘LD_LIBRARY_PATH’ environment variable,这是sqlite建议添加环境变量。 所以: echo expor…

「C/C++」C/C++异常处理

博客主页:何曾参静谧的博客 文章专栏:「C/C」C/C学习 目录 相关术语一、C语言中的异常处理1.返回值来传递错误信息2.使用标准库函数对异常进行处理(不推荐)3.使用全局变量来记录错误信息(不推荐) 二、C中的异常处理1.try{}catch()…

内外部函数静态变量全局变量

1、函数(封装、复用) 功能性:最基本的特性; 扩展性:对于时刻变化的需求易于扩展; 维护性:对于时刻变化的需求易于维护,易于编码变更; 封装性:不要把所有的代…