Node.js基礎:從入門到實戰

初識 Node.js 與內置模塊

(初識)
1、知道什么是node.js
2、知道node.js可以做什么
3、node.js 中js的組成部分
(內置模塊)
4、用 fs 模塊讀寫操作文件
5、使用 path 模塊處理路徑
6、使用http 模塊寫一個基本的web服務器

初識 Node.js

回顧與思考

回憶瀏覽器中的 JavaScript 組成:

在這里插入圖片描述

為什么JavaScript可以在瀏覽器中被執行,是因為瀏覽器中存在JavaScript解析引擎,而不同的瀏覽器使用的解析引擎是不一樣的:

在這里插入圖片描述

在這里插入圖片描述

因此可以總結出 JavaScript 的運行環境就包括下面兩個部分:

在這里插入圖片描述

由上述內容我們可以總結出兩點:

1、V8 引擎負責解析和執行 JavaScript 代碼

2、內置 API 是由運行環境提供的特殊接口,只能在所屬的運行環境中被調用

那么 JavaScript 能否做后端開發呢?

在這里插入圖片描述

當然是沒有問題的,JavaScript 本身只是一門語言,這門語言所編寫出來的代碼想要執行的話離不開運行時環境,如果將 JavaScript 的代碼放在瀏覽器里運行那么瀏覽器本身就是一個運行時環境,此時 JavaScript 就可以用來做前端開發,同時如果我們將 JavaScript 代碼放在 Node.js 環境(Node.js 也是一個 JavaScript 的運行時環境,只不過是一個后端的運行時環境)當中,通過 Node.js 就可以讓我們的 JavaScript 去做后端開發了。

Node.js 簡介

先來看一段官方的介紹:

在這里插入圖片描述

為什么是基于 Chrome V8 呢?之前說過,因為它最牛逼。所以使用 V8 來做 Node.js 的引擎用以解析 JavaScript 的代碼,這樣可以讓 JavaScript 跑的更快。

所以我們的 Chrome 瀏覽器和 Node.js 用的是同一款 JavaScript 解析引擎,即 V8 ;

只不過 V8 用在不同的地方做的事情是不一樣的,在 Chrome 瀏覽器中用 V8 解析 JavaScript 做的是前端的開發,而在 Node.js 中使用 V8 解析 JavaScript 則做的是后端開發,僅此而已。

Node.js 的運行時環境

在這里插入圖片描述

可以看見,Node.js 為我們提供了后端開發所需要的所有模塊的 API,因此學習 Node.js 很大程度上就是學習怎么使用這些內置的后端開發的 API。

Node.js 可以做什么

在這里插入圖片描述

一句話,全棧!

Node.js 怎么學

在這里插入圖片描述

Node.js 環境的安裝

在這里插入圖片描述

官方網址:Node.js

在這里插入圖片描述

直接下載完成后雙擊安裝即可,一路按照默認的來就行。

檢測安裝是否成功,打開 cmd 命令終端輸入 node -v,能正常顯示版本號即正常:

在這里插入圖片描述

這樣就安裝完成了。

什么是終端

在這里插入圖片描述

在 Node.js 環境中執行 JavaScript 代碼

下面介紹的是比較樸素的方式,因為現在都使用 IDE 了,我用的是 WebStorm,比較推薦,IDE 的使用就不介紹了,網上很多,不再贅述。

就兩步:

在這里插入圖片描述

先來寫一個 1.js 文件:

在這里插入圖片描述

然后進入終端,在當前文件目錄的命令行下,用 node 命令啟動即可:

在這里插入圖片描述

這樣就可以運行 JavaScript 代碼啦。

有一種便捷打開命令行的方式,即在我們的文件目錄下,按住 shift 后點擊鼠標右鍵會有一個打開 PowerShell 的選項:

在這里插入圖片描述

點擊它:

在這里插入圖片描述

可以看見這種方式更加的快捷,那么 PowerShell 和我們之前的 CMD 方式有什么區別呢?

CMD 方式是出現的比較早的一種方式,是舊版本的 windows 里的終端,后來 windows 做了升級,改成了 PowerShell ,也就是新版本的 CMD(其實用哪個都行,但是 PowerShell 的功能更加強大一些)。

終端中常用的一些快捷鍵:

在這里插入圖片描述

使用WebStorm編寫 Node.js 代碼沒有提示問題解決

參考這篇文章:使用WebStorm編寫 Node.js 代碼沒有提示問題解決

fs 文件系統模塊

什么是 fs 文件系統模塊

在這里插入圖片描述

我們只需要知道在安裝 Node.js 的時候這些模塊就都被安裝到電腦本地了即可,然后需要用到哪個模塊,就使用 require 方法將其導入進來即可。

讀取指定文件中的內容

fs.readFile() 的語法格式

在這里插入圖片描述

示例代碼如下:

// 1、到入 fs 模塊操作文件
const fs = require('fs')//2、調用 fs.readFile() 方法讀取文件
// 參數1、 讀取文件的存放路徑
// 參數2、 讀取文件時候采用的編碼格式,一般默認指定 utf8
// 參數3、 回調函數,拿到讀取失敗和成功的結果,err dataStr
fs.readFile('./1.txt', 'utf8', function (err, dataStr){// 打印失敗的結果// 如果讀取成功,則err 的值為null// 如果讀取失敗,則 err 的值為錯誤對象,dataStr 的值為 undefined// 因此可以通過判斷 err 對象是否為 null,來判斷文件讀取是否成功console.log(err)console.log("----------------")// 打印成功的結果// 如果讀取成功,那么dataStr就是從文件當中讀取的值// 如果讀取失敗,那么dataStr就是undefinedconsole.log(dataStr)
})

運行結果如下:

在這里插入圖片描述

關于fs.readFile()第三個參數是回調函數的解釋:
fs.readFile('./1.txt', 'utf8', function (err, dataStr){console.log(err)console.log("----------------")console.log(dataStr)
})

這段代碼中的回調函數是作為 fs.readFile 方法的最后一個參數傳遞進去的。根據 Node.js 中的約定,回調函數的第一個參數通常用于表示錯誤信息,第二個參數則是成功時返回的數據或結果(這是 fs.readFile() 函數的形式約定)。

所以,當你使用 fs.readFile 方法時,如果文件讀取成功,Node.js 會將 err 參數置為 null,而將文件內容作為 dataStr 參數傳遞給回調函數;如果文件讀取失敗,Node.js 會將 err 參數設置為相應的錯誤對象,而 dataStr 則會是 undefined。

因此,通過檢查 err 參數是否為 null,你可以輕松地判斷文件讀取是否成功。如果 err 為 null,則表示讀取成功,可以在 dataStr 中訪問文件內容;如果 err 不為 null,則表示讀取失敗,dataStr 會是 undefined,同時你可以查看 err 對象來了解具體的錯誤信息。

向指定的文件中寫入內容

fs.writerFile()的語法格式

在這里插入圖片描述

示例代碼如下:

const fs = require('fs')fs.writeFile('./2.txt', 'abcd', 'utf8', function (err){// 如果文件寫入成功,則 err 的值等于 null// 如果文件寫入失敗,則 err 的值等于一個錯誤對象console.log(err)
})

運行結果如下:

在這里插入圖片描述

因為運行成功,因此 err 是 null 值。

fs 模塊 - 路徑動態拼接的問題

在這里插入圖片描述

出現路徑拼接錯誤的問題,是因為提供了 ./ 或者 …/ 開頭的相對路徑。

如果要解決這個問題,可以直接提供一個完整的文件存放路徑(即絕對路徑)即可。

但是這又會帶來一種新的問題,就是代碼的移植性非常差,不利于維護。

那么如何完美解決這個問題呢?可以使用 Node.js 給我們提供的 __dirname 參數:

在這里插入圖片描述

測試也比較簡單,打印出來即可知道 __dirname 就是代表當前文件所處的目錄,因此不再贅述。

path 路徑模塊

什么是 path 路徑模塊

在這里插入圖片描述

路徑拼接

path.join() 的語法格式

在這里插入圖片描述

代碼示例如下:

const path = require('path')// 注意:../ 會抵消前面的路徑
const pathStr = path.join('/a','/b/c','../','./d','e')console.log(pathStr) // 輸出:\a\b\d\e//今后凡是涉及到路徑拼接的操作,都要使用 path.join() 方法進行處理。
// 不要用 + 進行字符串拼接
const pathFile = path.join(__dirname, '/a/1.txt')console.log(pathFile)

運行結果如下:

在這里插入圖片描述

獲取路徑中的文件名

path.basename() 的語法格式

在這里插入圖片描述

示例代碼:

const path = require('path')//定義文件的存放路徑
const fpath = '/a/b/c/index.html'const fullName = path.basename(fpath)
console.log(fullName) //輸出:index.htmlconst nameWithoutExt = path.basename(fpath, '.html')
console.log(nameWithoutExt) //輸出:index

運行結果如下:

在這里插入圖片描述

獲取路徑中的文件擴展名

path.extname() 的語法格式

在這里插入圖片描述

示例代碼如下:

const path = require('path')//這是文件的存放路徑
const fpath = '/a/b/c/index.html'const fext = path.extname(fpath)console.log(fext)

運行結果如下:

在這里插入圖片描述

關于 path 模塊需要注意的兩個小點

在這里插入圖片描述

http 模塊

什么是 http 模塊

在這里插入圖片描述

進一步理解 http 模塊的作用:

在這里插入圖片描述

創建最基本的 web 服務器

在這里插入圖片描述

上面的步驟細分下來其實就是下面這樣:

第一步:導入 http 模塊

在這里插入圖片描述

第二步:創建 web 服務器實例

在這里插入圖片描述

第三步:為服務器實例綁定 request 事件

在這里插入圖片描述

第四步:啟動服務器

在這里插入圖片描述

接下來我們來代碼實操一下:

//1、導入 http模塊
const http = require('http')
//2、創建 web 服務器實例
server = http.createServer()
//3、為服務器實例綁定 request 事件,監聽客戶端的請求
server.on('request', function (req, res){console.log('Someone visit our web server.')
})
//4、啟動服務器
server.listen(80,function (){console.log('Server running at http://127.0.0.1')
})

運行效果如下:

在這里插入圖片描述

在這里插入圖片描述

可以發現當我們在瀏覽器訪問該地址的時候,我們的監聽事件已經監聽到了事件。

補充:什么是箭頭函數

這是 JavaScript 中的箭頭函數語法。()=>{} 是一個簡單的箭頭函數,它表示一個沒有參數的函數,并返回一個空對象(即函數體內沒有執行任何操作)。箭頭函數是 ES6(ECMAScript 2015)中引入的一種新的函數聲明方式,它可以更簡潔地定義函數,并且在一些情況下具有更清晰的語義。

req 請求對象

在這里插入圖片描述

代碼示例如下:

const http = require('http')
server = http.createServer()
// req 是請求對象,包含了與客戶端相關的數據和屬性
server.on('request', (req)=>{// req.url 是客戶端請求的 url 地址const url = req.url//req.method 是客戶端請求的 method 類型const method = req.methodconst str = `Your request url is ${url}, and request method is ${method}`console.log(str)
})server.listen(80,function (){console.log('Server running at http://127.0.0.1')
})

運行效果如下:

在這里插入圖片描述

在這里插入圖片描述

res 響應對象

在這里插入圖片描述

示例代碼如下:

const http = require('http')
server = http.createServer()
// req 是請求對象,包含了與客戶端相關的數據和屬性
server.on('request', (req, res)=>{// req.url 是客戶端請求的 url 地址const url = req.url//req.method 是客戶端請求的 method 類型const method = req.methodconst str = `Your request url is ${url}, and request method is ${method}`console.log(str)// 調用 res.end() 方法向客戶端響應一些內容res.end(str)
})server.listen(80,function (){console.log('Server running at http://127.0.0.1')
})

運行效果如下:

在這里插入圖片描述

解決中文亂碼的問題

在這里插入圖片描述

代碼示例如下:

const http = require('http')
server = http.createServer()
// req 是請求對象,包含了與客戶端相關的數據和屬性
server.on('request', (req, res)=>{// req.url 是客戶端請求的 url 地址const url = req.url//req.method 是客戶端請求的 method 類型const method = req.methodconst str = `你的請求路徑是 ${url}, 請求方法是 ${method}`console.log(str)// 發送數據前設置響應頭,設置編碼方式res.setHeader('Content-Type', 'text/html; charset=utf-8')// 調用 res.end() 方法向客戶端響應一些內容res.end(str)
})server.listen(80,function (){console.log('Server running at http://127.0.0.1')
})

運行效果如下:

在這里插入圖片描述

根據不同的 url 響應不同的 html 內容

在這里插入圖片描述

動態響應內容的代碼示例:

const http = require('http')server = http.createServer()// req 是請求對象,包含了與客戶端相關的數據和屬性
server.on('request', (req, res)=>{//1、獲取請求的 url 地址const url = req.url//2、設置默認的響應內容為 404 Not Foundlet content = '404 Not Found'//3、判斷用戶請求的是否為 / 或者 /index.html 頁面//4、判斷用戶請求的是否為 /about.html 關于頁面if(url === '/' || url === '/index.html'){content = '<h1>首頁</h1>'}else if(url === '/about.html'){content = '<h1>關于頁面</h1>'}//5、設置 Content-Type 響應頭,防止中文亂碼res.setHeader('Content-Type', 'text/html; charset=utf-8')//6、使用 res.end() 把內容響應給客戶端res.end(content)
})server.listen(80,function (){console.log('Server running at http://127.0.0.1')
})

運行效果如下:

在這里插入圖片描述

在這里插入圖片描述

補充:${} 模板字符串語法

${} 是 JavaScript 中的模板字符串語法。在字符串中使用 ${} 可以插入變量或表達式的值。在這種情況下,${url} 表示將變量 url 的值插入到字符串中。這種語法使得字符串拼接更加清晰和簡潔。

模塊化

在這里插入圖片描述

模塊化的基本概念

模塊化是指解決一個復雜問題時,自頂向下逐層把系統劃分為若干模塊的過程。對于整個系統來說,模塊是可組合、分解和更換的單元。

在這里插入圖片描述

模塊化規范

在這里插入圖片描述

Node.js 中模塊的分類

在這里插入圖片描述

加載模塊

在這里插入圖片描述

注意:在使用 require 加載用戶自定義模塊期間,可以省略 .js 的后綴名。

Node.js 中的模塊作用域

在這里插入圖片描述

模塊作用域的好處就是:防止了全局變量污染的問題。

向外共享模塊作用域中的成員

module 對象

在這里插入圖片描述

module.exports 對象

在這里插入圖片描述

接下來我們用代碼來解釋一下。

先創建兩個自定義模塊,一個是自定義模塊.js 另一個是 test.js,然后我們 自定義模塊.js 文件先不寫任何內容,在 test.js 中先去 require 自定義模塊.js 中的內容試一下:

在這里插入圖片描述

運行效果如下:

在這里插入圖片描述

可以看見打印不出任何內容,因為我們在導入另一個模塊的時候,我們導入的其實是另一個模塊 module 的 exports 屬性,默認情況下 exports 屬性就是空的,這可以從上一小節講的 module 對象 中的圖里看到。

因此我們其實可以在 自定義模塊.js 中對外共享一些本模塊中的成員:

在這里插入圖片描述

此時我們在運行 test.js 查看現在是否 modules.export 為空了:

在這里插入圖片描述

可以看見不為空了,有內容的。

共享成員時的注意點

在這里插入圖片描述

exports 對象

在這里插入圖片描述

代碼驗證如下:

console.log(exports)
console.log(module.exports)
console.log(exports === module.exports)

運行效果如下:

在這里插入圖片描述

exports 和 module.exports 的使用誤區

在這里插入圖片描述

Node.js 中的模塊化規范

在這里插入圖片描述

npm 與包

什么是包

在這里插入圖片描述

包的來源

在這里插入圖片描述

為什么需要包

在這里插入圖片描述

從哪里下載包

在這里插入圖片描述

如何下載包

在這里插入圖片描述

查看自己電腦上的 npm 版本:

在這里插入圖片描述

npm 初體驗

在這里插入圖片描述

這種傳統方法就不演示了,可以看出來很繁瑣,因此我們直接使用第三方包來完成一樣的事情:

在這里插入圖片描述

在項目中安裝包的命令

在這里插入圖片描述

接下來我們來演示如何用 npm 下載 第三方包,這里我直接使用 WebStorm 的終端進行下載了:

在這里插入圖片描述

可以看見此時就已經下載安裝好了。

寫代碼來實現我們的時間格式化操作:

//1、導入需要的包
const moment = require('moment')//2、查閱官方文檔明白第三方包要如何使用
const dt = moment().format('YYYY-MM-DD HH:mm:ss')
console.log(dt)

運行效果如下:

在這里插入圖片描述

初次安裝后都多了哪些文件

在這里插入圖片描述

可以檢查一下自己的項目:

在這里插入圖片描述

注意:程序員不要手動修改 node_modules 或者 package-lock.json 文件中的任何代碼,npm 包管理工具會自動維護它們。

安裝指定版本的包

在這里插入圖片描述

注意:如果我們要切換第三方包的版本并不需要先卸載我們現有版本的包,而是直接下新的即可,新的會覆蓋原來舊版本的包嗷。

包的語義化版本規范

在這里插入圖片描述

包管理配置文件

在這里插入圖片描述

多人協作的問題

在這里插入圖片描述

如何記錄項目中安裝了哪些包

在這里插入圖片描述

快速創建 package.json

在這里插入圖片描述

dependencies 節點

在這里插入圖片描述

一次性安裝所有的包

在這里插入圖片描述
在這里插入圖片描述

卸載包

在這里插入圖片描述

devDependencies 節點

在這里插入圖片描述

怎么知道哪些第三方包需要被保存到 devDependencies 哪些需要被保存到 dependencies 呢?

這些其實在官方文檔都會有說的,查閱官方文檔就行。

為什么下包速度慢

在這里插入圖片描述

下包速度慢解決:淘寶 NPM 鏡像服務器

在這里插入圖片描述

切換 NPM 的下包鏡像源

在這里插入圖片描述

nrm 小工具

在這里插入圖片描述

包的分類

使用 npm 包管理工具下載的包,共分為兩大類,分別是:項目包和全局包。

在這里插入圖片描述

在這里插入圖片描述

好用的第三方包:i5ting_toc

在這里插入圖片描述

規范的包結構

在這里插入圖片描述

package.json 為啥必須要包含 main 包入口的這個屬性呢?

這是因為在我們項目中使用 require 導入第三方包的時候其實走的就是這個 main 屬性,通過這個 main 屬性我們才能正常使用這個包的功能,即它是包的入口。

開發屬于自己的包

假設我們現在需要開發的包叫 itheima-tools 包,其需要實現下面的功能:

在這里插入圖片描述

那么接下來我們就按照下面的步驟開發我們自己的包:

在這里插入圖片描述

實現效果如下:

在這里插入圖片描述

然后初始化 package.json :

在這里插入圖片描述

如果你使用 WebStorm 進行文件創建的話,可以發現其是自動生成的,只要點擊創建就可以了。

不難發現這個 package.json 包其實就是一個 json 配置對象:

在這里插入圖片描述

但是我們需要改一下,改成 PPT 中的那樣,否則沒辦法發布到 NPM 的服務器上:

在這里插入圖片描述

上面需要解釋的幾個含義:

main:就是入口文件的位置
keywords:這是被發布到 npm 服務器上時別人可以檢索到這個包所使用的關鍵字有哪些
license:所遵循的開源許可協議,npm 官方推薦使用 ISC,因此我們用這個即可

然后編寫我們的包源碼:

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

將不同的功能進行模塊化拆分

在這里插入圖片描述

src 是我們的新創建的源碼文件夾,拆分的部分將全部放進該文件夾中。

編寫包的說明文檔

在這里插入圖片描述

發布包

主要有以下幾個步驟:

在這里插入圖片描述

在這里插入圖片描述

注意:在運行 npm login 命令之前,必須先把下包的服務器地址切換為 npm 的官方服務器。否則會導致發布包失敗!

在這里插入圖片描述

刪除已發布的包

在這里插入圖片描述

模塊的加載機制

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

Express.js

在這里插入圖片描述

初識 Express.js

Express.js 簡介

在這里插入圖片描述

進一步理解 Express

在這里插入圖片描述

Express 能做什么

在這里插入圖片描述

Express 安裝

在這里插入圖片描述

這里看的課的老師用的 4.17.1 的版本,我看了一下現在官網的最新版本是 4.19.2:

按照包的語義化版本規范,因為是只上升了第二位數的大小,說明相較于 4.17.1 的版本,現在最新的版本也只不過是新增了一些功能并且修復了一點 bug 而已,因此我們直接安裝使用最新版即可:

在這里插入圖片描述

查看版本:

在這里插入圖片描述

Express 創建 web 服務器

在這里插入圖片描述

來實現一下:

// 1、導入 Express
const express = require('express')
// 2、創建 web 服務器
const app = express()
// 3、啟動 web 服務器
// 調用 app.listen(端口號,啟動成功后的回調函數),啟動服務器
app.listen(80, ()=>{console.log('express server running at http://127.0.0.1')
})

運行效果如下:

在這里插入圖片描述

Express 監聽 Get 和 Post 請求

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

示例代碼如下:

// 1、導入 Express
const express = require('express')
// 2、創建 web 服務器
const app = express()//4、監聽客戶端的 Get 和 Post 請求,并向客戶端響應具體的內容
app.get('/user',(req,res) => {//調用 express 提供的 res.send() 方法,向客戶端響應一個 JSON 對象res.send({name: 'zs',age : 20,gender: '男'})
})app.post('/user',(req,res) => {//調用 express 提供的 res.send() 方法,向客戶端響應一個文本字符串res.send('請求成功')
})// 3、啟動 web 服務器
app.listen(80, ()=>{console.log('express server running at http://127.0.0.1')
})

效果如下:

在這里插入圖片描述

獲取 URL 中攜帶的查詢參數

在這里插入圖片描述

示例代碼如下:

app.get('/', (req,res)=>{//通過 req.query 可以獲取到客戶端發送過來的 查詢參數//注意:默認情況下,req.query 是一個空對象console.log(req.query)res.send(req.query)
})

運行結果如下:

在這里插入圖片描述

此時我們加上查詢參數運行結果將變為:

在這里插入圖片描述

獲取 URL 中的動態參數

在這里插入圖片描述

示例代碼如下:

//注意:這里的 :id 是一個動態的參數
app.get('/user/:id',(req,res)=>{// req.params 是動態匹配到的 URL 參數,默認是空對象console.log(req.params)res.send(req.params)
})

運行效果如下:

在這里插入圖片描述

我們不止可以寫一個,可以寫多個動態參數:

//注意:這里的 :id 是一個動態的參數
app.get('/user/:id/:name',(req,res)=>{// req.params 是動態匹配到的 URL 參數,默認是空對象console.log(req.params)res.send(req.params)
})

運行效果如下:

在這里插入圖片描述

托管靜態資源

express.static()

在這里插入圖片描述

簡單測試一下:

在這里插入圖片描述

運行效果如下:

在這里插入圖片描述

托管多個靜態資源目錄

在這里插入圖片描述

掛載路徑前綴

在這里插入圖片描述

調試工具:nodemon 的安裝與使用

在這里插入圖片描述
在這里插入圖片描述

在這里插入圖片描述

Express 路由

什么是路由

廣義上講,路由就是映射關系。

比如:

在這里插入圖片描述

在上圖中,路由就是按鍵與服務之間的映射關系。

Express 中的路由

在這里插入圖片描述

實際項目中的示例程序:

在這里插入圖片描述

路由的匹配過程

在這里插入圖片描述

路由的使用

在這里插入圖片描述

這種方式之前就用過很多次了,只要知道有這種用法即可,實際的項目中我們不會采用這么直接的方式,因此不再贅述。

模塊化路由

在這里插入圖片描述

創建路由模塊

在這里插入圖片描述

我們新創建一個 router.js 模塊,也就是一個自定義模塊,在其內部創建和掛載我們的路由模塊:

// 這是路由模塊//1、導入 express
const express = require('express')
//2、創建路由對象
const router = express.Router()
//3、掛載具體的路由
router.get('/user/list',(req,res) => {res.send('Get user list')
})router.post('/user/add',(req,res) => {res.send('Add a new user')
})
//4、向外導出路由對象
module.exports = router
注冊路由模塊
// 1、導入 Express
const express = require('express')
// 2、創建 web 服務器
const app = express()// 1、導入路由模塊
const router = require('./router.js')
// 2、注冊路由模塊
app.use(router)// 3、啟動 web 服務器
app.listen(80, ()=>{console.log('express server running at http://127.0.0.1')
})

運行效果如下:

在這里插入圖片描述

可以發現路由模塊化后也依然可以正常工作。

app.use() 函數的作用

一句話:該函數的作用就是用來注冊全局中間件的(后面就會講到了)。

為路由模塊添加前綴

在這里插入圖片描述

Express 中間件

什么是中間件

中間件(Middleware),特指業務流程的中間處理環節。

比如:

在這里插入圖片描述

Express 中間件的調用流程

在這里插入圖片描述

Express 中間件的格式

在這里插入圖片描述

next 函數的作用

在這里插入圖片描述

Express 中間件的初體驗

在這里插入圖片描述

代碼示例如下:

const express = require('express')const app = express()// 定義一個最簡單的中間件函數
const mw = function (req, res, next){console.log("這是最簡單的中間件函數")//把流轉關系,轉交給下一個中間件或者路由//(有中間件轉交給中間件,沒中間件就轉交給路由)next()
}app.listen(80, () => {console.log('http://localhost')
})

全局生效的中間件

在這里插入圖片描述

示例代碼如下:

const express = require('express')const app = express()// 定義一個最簡單的中間件函數
const mw = function (req, res, next){console.log("這是最簡單的中間件函數")//把流轉關系,轉交給下一個中間件或者路由//(有中間件轉交給中間件,沒中間件就轉交給路由)next()
}//將 mw 注冊為全局生效的中間件
app.use(mw)app.get('/',(req,res)=>{console.log('Here is Home Page')res.send('Home page')
})app.get('/user',(req,res)=>{res.send('User page')
})app.listen(80, () => {console.log('http://localhost')
})

運行效果如下:

在這里插入圖片描述

可以看見訪問瀏覽器時是成功打印了:

在這里插入圖片描述

因為目前我們只定義了一個中間件,因此在 mw 中間件函數執行結束之后因為沒有其他中間件了,于是 next() 函數將流轉關系轉交給了路由模塊,所以先打印 “這是最簡單的中間件函數” 再打印 “Here is Home Page”。

定義全局中間件的簡化形式

在這里插入圖片描述

中間件的作用

在這里插入圖片描述

示例代碼:

const express = require('express')const app = express()// 定義一個最簡單的中間件函數
const mw = function (req, res, next){//獲取請求到達服務器的時間const time = Date.now()//為 req 對象掛載自定義屬性,從而把時間共享給后面的所有路由req.startTime = time//把流轉關系,轉交給下一個中間件或者路由//(有中間件轉交給中間件,沒中間件就轉交給路由)next()
}//將 mw 注冊為全局生效的中間件
app.use(mw)app.get('/',(req,res)=>{res.send('Home page'+req.startTime)
})app.get('/user',(req,res)=>{res.send('User page'+req.startTime)
})app.listen(80, () => {console.log('http://localhost')
})

運行效果:

在這里插入圖片描述

定義多個全局中間件

在這里插入圖片描述

局部生效的中間件

在這里插入圖片描述

定義多個局部中間件

在這里插入圖片描述

注意調用順序是從前往后的,即先執行 mw1 再執行 mw2。

了解中間件使用的5個使用注意事項

在這里插入圖片描述

中間件的分類

在這里插入圖片描述

應用級別的中間件:

在這里插入圖片描述

路由級別的中間件:

在這里插入圖片描述

錯誤級別的中間件:

在這里插入圖片描述

注意:錯誤級別的中間件,必須注冊在所有路由之后!

Express 內置的中間件

在這里插入圖片描述

express.json() 內置中間件

代碼示例:

const express = require('express')
const app = express()//注意:除了錯誤級別的中間件,其他的中間件,必須在路由之前進行配置
//通過 express.json() 這個中間件,解析表單中的 JSON 格式的數據
app.use(express.json())app.post('/user',(req,res)=>{// 在服務器中可以使用 req.body 這個屬性來接收客戶端發送過來的請求體數據// 默認情況下,如果不配置解析表單數據的中間件(也就是 express.json()),則 req.body 默認為 undefinedconsole.log(req.body)res.send('ok')
})app.listen(80, ()=>{console.log('http://localhost')
})

運行效果,我們使用 postman 工具來進行測試:

發送 JSON 類型的請求體數據如下:

在這里插入圖片描述

此時控制臺中的輸出如下:

在這里插入圖片描述

可以看見請求體數據被完美解析。

express.urlencoded() 內置中間件

示例代碼如下:

const express = require('express')
const app = express()//注意:除了錯誤級別的中間件,其他的中間件,必須在路由之前進行配置
//通過 express.urlencoded() 這個中間件,解析表單中的 JSON 格式的數據
//在這個函數內部我們還要傳遞一個固定的配置對象 extended ,將其設置為 false
//這是固定的寫法,只需要記住,不需要問為什么
app.use(express.urlencoded({ extended: false }))app.post('/book',(req,res)=>{// 在服務器中可以使用 req.body 這個屬性來接收客戶端發送過來的 url-encoded 格式的數據// 默認情況下,如果不配置解析 url-encoded 表單數據的中間件,則 req.body 默認為空console.log(req.body)res.send('ok')
})app.listen(80, ()=>{console.log('http://localhost')
})

發送數據類型為:

在這里插入圖片描述

運行效果為:

在這里插入圖片描述

可以看見正常解析了數據。

第三方中間件

在這里插入圖片描述

自定義中間件

在這里插入圖片描述

實現如下:

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

使用 Express 寫 API 接口

1、創建基本的服務器:

// app.js 主模塊
// 導入 express
const express = require('express')// 創建服務器實例
const app = express()// 調用 app.listen() 方法,指定端口號并啟動 web 服務器
app.listen(80,()=>{console.log('Express server is running at http://localhost')
})

2、創建 API 路由模塊

// apiRouter.js 路由模塊
const express = require('express')const router = express.Router()//在這里掛載對于的路由module.exports = router

然后在 app.js 中導入并注冊路由模塊:

// app.js 主模塊
// 導入 express
const express = require('express')// 創建服務器實例
const app = express()//導入路由模塊
const router = require('./apiRouter')
//把路由模塊注冊到 app 上
app.use('/api', router)// 調用 app.listen() 方法,指定端口號并啟動 web 服務器
app.listen(80,()=>{console.log('Express server is running at http://localhost')
})

3、編寫 Get 接口

// apiRouter.js 路由模塊
const express = require('express')const router = express.Router()//在這里掛載對應的路由
router.get('/get', (req,res)=>{//通過 req.query 獲取客戶端通過查詢字符串,發送到服務器的數據const query = req.query//調用 res.send() 方法,向客戶端響應處理的結果res.send({stats: 0,//0 表示處理成功,1 表示處理失敗msg: 'Get 請求成功', // 狀態描述data: query //需要響應給客戶端的數據})
})module.exports = router

運行結果如下:

在這里插入圖片描述

4、編寫 Post 接口

// apiRouter.js 路由模塊
const express = require('express')const router = express.Router()//在這里掛載對應的路由
router.get('/get', (req,res)=>{//通過 req.query 獲取客戶端通過查詢字符串,發送到服務器的數據const query = req.query//調用 res.send() 方法,向客戶端響應處理的結果res.send({stats: 0,//0 表示處理成功,1 表示處理失敗msg: 'Get 請求成功', // 狀態描述data: query //需要響應給客戶端的數據})
})router.post('/post', (req,res)=>{//通過 req.body 獲取客戶端發送到服務器的請求體數據const body = req.body//調用 res.send() 方法,向客戶端響應處理的結果res.send({stats: 0,//0 表示處理成功,1 表示處理失敗msg: 'Post 請求成功', // 狀態描述data: body //需要響應給客戶端的數據})
})module.exports = router

要解析表單數據別忘了在導入路由之前先添加配置解析表單數據的中間件:

// app.js 主模塊
// 導入 express
const express = require('express')// 創建服務器實例
const app = express()//配置解析表單數據的中間件
app.use(express.urlencoded({ extended: false}))
app.use(express.json())//導入路由模塊
const router = require('./apiRouter')
//把路由模塊注冊到 app 上
app.use('/api', router)// 調用 app.listen() 方法,指定端口號并啟動 web 服務器
app.listen(80,()=>{console.log('Express server is running at http://localhost')
})

運行效果如下:

在這里插入圖片描述

接口的跨域問題

在這里插入圖片描述

接口跨域問題是指在Web開發中,由于瀏覽器的同源策略(Same-Origin Policy),導致在一個域下的網頁無法直接訪問另一個域下的資源。"跨域"指的是在瀏覽器中,當一個頁面的腳本請求訪問另一個域下的資源時,如果這個資源的域名、協議或端口與當前頁面所在的域不一致,就會引發跨域問題。

跨域問題會影響到包括Ajax請求、Web字體加載、嵌入式框架(如iframe)加載等場景。具體來說,如果你在一個網頁中使用Ajax請求另一個域下的數據,瀏覽器會阻止這個請求,因為涉及到跨域。

解決接口跨域問題的方法有很多,包括使用代理服務器、JSONP、CORS(跨域資源共享)等。CORS是一種比較常用的解決方案,它通過在服務器端設置一些響應頭,來告訴瀏覽器允許跨域請求。JSONP則是一種利用

實際開發中,我們推薦使用 CORS 的方法來解決跨域問題。

使用 CORS 中間件解決跨域問題

在這里插入圖片描述

第一步:安裝

在這里插入圖片描述

第二步和第三步:在路由之前先配置并注冊 cors 中間件到 app.js 上

// app.js 主模塊
// 導入 express
const express = require('express')// 創建服務器實例
const app = express()//配置解析表單數據的中間件
app.use(express.urlencoded({ extended: false}))
app.use(express.json())//在路由之前先配置 cors 中間件解決跨域問題
const cors = require('cors')
//注冊 cors 中間件
app.use(cors())//導入路由模塊
const router = require('./apiRouter')
//把路由模塊注冊到 app 上
app.use('/api', router)// 調用 app.listen() 方法,指定端口號并啟動 web 服務器
app.listen(80,()=>{console.log('Express server is running at http://localhost')
})

這樣就可以解決跨域問題啦。

什么是 CORS

在這里插入圖片描述

CORS 的注意事項

在這里插入圖片描述

CORS 響應頭部 -Access-Control-Allow-Origin

在這里插入圖片描述

在這里插入圖片描述

CORS 響應頭部 -Access-Control-Allow-Headers

在這里插入圖片描述

CORS 響應頭部 -Access-Control-Allow-Methods

在這里插入圖片描述

CORS 請求的分類

在這里插入圖片描述

簡單請求

在這里插入圖片描述

預檢請求

在這里插入圖片描述

在瀏覽器與服務器正式通信之前,瀏覽器會先發送 OPTION 請求進行預檢,以獲知服務器是否允許該實際請求,所以這一次的 OPTION 請求稱為 ”預檢請求“ 。服務器成功響應預檢請求后,才會發送真正的請求,并且攜帶真實數據。

簡單請求和預檢請求之間的區別

在這里插入圖片描述

數據庫與身份認證

在這里插入圖片描述

注意這一章節的學習中省略了 MySQL 相關的基礎內容,如果不會的話建議先去系統學一下 MySQL 捏。

這里只講 Express 中如何操作 MySQL 數據庫嗷。

測試的表數據如下:

在這里插入圖片描述

在 Express 中操作 MySQL

在項目中操作 MySQL 數據庫的步驟:

在這里插入圖片描述

安裝 mysql 模塊:

在這里插入圖片描述

配置 mysql 模塊:

在這里插入圖片描述

示例代碼如下:

//mysql-cfg.js 數據庫模塊
//1、導入 mysql 模塊
const mysql = require('mysql')//2、建議與 mysql 數據庫的連接關系
const db = mysql.createPool({host: '127.0.0.1', //數據庫的 ip 地址user: 'root', //登錄數據庫的賬號password: '123456', //登錄數據庫的密碼database: 'node' //指定要操作哪一個數據庫
})

測試一下 mysql 模塊是否能正常工作:

//mysql-cfg.js 數據庫模塊
//1、導入 mysql 模塊
const mysql = require('mysql')//2、建議與 mysql 數據庫的連接關系
const db = mysql.createPool({host: '127.0.0.1', //數據庫的 ip 地址user: 'root', //登錄數據庫的賬號password: '123456', //登錄數據庫的密碼database: 'node' //指定要操作哪一個數據庫
})// 測試 mysql 模塊能否正常工作
// select 1 這條語句沒有任何意義,只是用來檢查 mysql 能否正常工作
db.query('select 1',(err, results)=>{// mysql 模塊工作期間報錯了if(err){return console.log(err.message)}//否則就是能夠正常的執行 SQL 語句console.log(results)
})

測試運行結果如下:

在這里插入圖片描述

可以看見我們的 mysql 模塊是沒有問題的。

使用 mysql 模塊操作 MySQL 數據庫

查詢數據

在這里插入圖片描述

示例代碼如下:

//mysql-cfg.js 數據庫模塊
//1、導入 mysql 模塊
const mysql = require('mysql')//2、建議與 mysql 數據庫的連接關系
const db = mysql.createPool({host: '127.0.0.1', //數據庫的 ip 地址user: 'root', //登錄數據庫的賬號password: '123456', //登錄數據庫的密碼database: 'node' //指定要操作哪一個數據庫
})// 查詢 users 表中所有的數據
const str = "select * from user"
db.query(str,(err, results)=>{// mysql 模塊工作期間報錯了if(err){return console.log(err.message)}//否則就是能夠正常的執行 SQL 語句console.log(results)
})

運行結果如下:

在這里插入圖片描述

注意:如果執行的是 select 查詢語句,則執行的結果是數組。

插入數據

在這里插入圖片描述

示例代碼:

//mysql-cfg.js 數據庫模塊
//1、導入 mysql 模塊
const mysql = require('mysql')//2、建議與 mysql 數據庫的連接關系
const db = mysql.createPool({host: '127.0.0.1', //數據庫的 ip 地址user: 'root', //登錄數據庫的賬號password: '123456', //登錄數據庫的密碼database: 'node' //指定要操作哪一個數據庫
})// 向 user 表中新增一條數據,其中username的值為 Spider,password 的值為123
const user = {username:'Spider', password:'123'}
//定義待執行的 SQL 語句
const sqlStr = 'insert into user (username, password) values (?, ?)'
//執行 SQL 語句
db.query(sqlStr,[user.username,user.password],(err,results)=>{if(err) return console.log(err.message)// 注意:如果執行的是 insert into 插入語句,則 results 是一個對象// 可以通過 affectedRows 屬性,來判斷是否插入數據成功if(results.affectedRows === 1) console.log('插入數據成功')
})

插入數據的便捷方式

在這里插入圖片描述

示例代碼:

//mysql-cfg.js 數據庫模塊
//1、導入 mysql 模塊
const mysql = require('mysql')//2、建議與 mysql 數據庫的連接關系
const db = mysql.createPool({host: '127.0.0.1', //數據庫的 ip 地址user: 'root', //登錄數據庫的賬號password: '123456', //登錄數據庫的密碼database: 'node' //指定要操作哪一個數據庫
})// 向 user 表中新增一條數據,其中username的值為 Spider,password 的值為123
const user = {username:'Spider', password:'123'}
//定義待執行的 SQL 語句
//insert into 表名 set ?
const sqlStr = 'insert into user set ?'
//執行 SQL 語句
// 參數也不需要用數組形式了,直接將原對象進行插入即可(類似于一個 JavaBean)
db.query(sqlStr,user,(err,results)=>{if(err) return console.log(err.message)// 注意:如果執行的是 insert into 插入語句,則 results 是一個對象// 可以通過 affectedRows 屬性,來判斷是否插入數據成功if(results.affectedRows === 1) console.log('插入數據成功')
})

運行結果如下:

在這里插入圖片描述

數據庫中也是正常的新增了數據:

在這里插入圖片描述

更新數據

在這里插入圖片描述

示例代碼:

//mysql-cfg.js 數據庫模塊
//1、導入 mysql 模塊
const mysql = require('mysql')//2、建議與 mysql 數據庫的連接關系
const db = mysql.createPool({host: '127.0.0.1', //數據庫的 ip 地址user: 'root', //登錄數據庫的賬號password: '123456', //登錄數據庫的密碼database: 'node' //指定要操作哪一個數據庫
})// 向 user 表中修改一條數據
const user = { id: 3, username:'阿斯頓', password:'123' }
//定義待執行的 SQL 語句
const sqlStr = 'update user set username=?,password=? where id=?'
//執行 SQL 語句
db.query(sqlStr,[user.username,user.password,user.id],(err,results)=>{if(err) return console.log(err.message)// 注意:如果執行的是 update 更新語句,則 results 是一個對象// 可以通過 affectedRows 屬性,來判斷是否更新數據成功if(results.affectedRows === 1) console.log('更新數據成功')
})

運行結果如下:

在這里插入圖片描述

更新數據的便捷方式

在這里插入圖片描述

刪除數據

在這里插入圖片描述

標記刪除

在這里插入圖片描述

前后端中的身份認證

Web 開發模式

目前主流的 Web 開發模式有兩種,分別是:

1、基于服務端渲染的傳統 Web 開發模式

2、基于前后端分離的新型 Web 開發模式

基于服務端渲染的傳統 Web 開發模式

在這里插入圖片描述
在這里插入圖片描述

基于前后端分離的新型 Web 開發模式

在這里插入圖片描述

在這里插入圖片描述

如何選擇 Web 開發模式

在這里插入圖片描述

身份認證

什么是身份認證?
在這里插入圖片描述

為什么需要身份認證

在這里插入圖片描述

不同開發模式下的身份認證

在這里插入圖片描述

HTTP 協議的無狀態性

在這里插入圖片描述

如何突破 HTTP 無狀態的限制

在這里插入圖片描述

什么是 Cookie

在這里插入圖片描述

Cookie 在身份認證中的作用

在這里插入圖片描述

Cookie 不具有安全性

在這里插入圖片描述

注意:千萬不要使用 Cookie 存儲重要且隱私的數據!比如用戶的身份信息、密碼等。

提高身份認證的安全性

在這里插入圖片描述

Session 的工作原理

在這里插入圖片描述

在 Express 中使用 Session 認證

配置 Session

只需要下面幾步就可以使用 Session 認證了嗷:

在這里插入圖片描述
在這里插入圖片描述

配置對象中的 secret 屬性是一串字符串,用來加密用的。

接下來我們完成一下這些事情:

安裝 express-session 中間件:

在這里插入圖片描述

開始配置 express-session 的全局中間件:

// app.js 主模塊
// 導入 express
const express = require('express')// 創建服務器實例
const app = express()// 引入session
const session = require('express-session')
// 注冊 session
app.use(session({secret: 'hahaha',resave: false,saveUninitialized: true
}))//配置解析表單數據的中間件
app.use(express.urlencoded({ extended: false}))
app.use(express.json())//在路由之前先配置 cors 中間件解決跨域問題
const cors = require('cors')
//注冊 cors 中間件
app.use(cors())//導入路由模塊
const router = require('./apiRouter')
//把路由模塊注冊到 app 上
app.use('/api', router)// 調用 app.listen() 方法,指定端口號并啟動 web 服務器
app.listen(80,()=>{console.log('Express server is running at http://localhost')
})
向 Session 中存數據

在這里插入圖片描述

從 Session 中取數據

在這里插入圖片描述

清空 Session

在這里插入圖片描述

注意:只是清空了當前客戶端的 Session ,這并不會影響到其他客戶端的 Session。

因為之前說過 Session 的工作原理,每個 Session 都會對應一個客戶端瀏覽器所自動存收的一個 Cookie,因此相當于各個客戶端之間是隔離連接的,互不影響,至于底層是怎么實現的應該是在這個 express-session 第三方包中自動實現的,我們只要懂得怎么使用即可。

了解 Session 認證的局限性

在這里插入圖片描述

什么是 JWT

JWT(英文全稱:JSON Web Token)是目前最流行的跨域認證解決方案。

JWT 的工作原理

在這里插入圖片描述

JWT 的組成部分

在這里插入圖片描述

JWT 的三個部分各自代表的含義

在這里插入圖片描述

JWT 的使用方式

在這里插入圖片描述

注意:千萬別忘記了在 token 字符串前加 Bearer 這個字符串!然后后面還要跟一個空格才能再跟 token 字符串!!!

比如我們在 postman 中要帶 token 的話,那么形式應該是下面這樣:

在這里插入圖片描述

在 Express 中使用 JWT

主要有下面幾個步驟:

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

上圖中的第三個參數配置對象里,我們配置了該 Token 的過期時間為 30s,如果要設置成分鐘則后綴用 m ,小時的話設置為 h 即可。

在這里插入圖片描述

注意:只要配置成功了 express-jwt 這個中間件,就可以把解析出來的用戶信息,掛載到 req.user 屬性上。

換句話說就是,req 本身是沒有 user 屬性的,但是只要配置成功了 express-jwt 這個中間件后,req 就有一個 user 屬性了,該屬性是由該中間件創建的。

而這個 user 對象中包含多少信息是由我們自己決定的,也就是在登錄成功之后我們進行加密的用戶信息對象信息有多少那么 user 對象中就有多少信息。

比如我們上面的示例中將 username 進行了加密,那么被創建的 user 對象就會只有一個 username 屬性。

如果我們的訪問請求攜帶了 token 進行 API 訪問的話,其返回值會有下面兩個額外的屬性:

在這里插入圖片描述

iat 和 exp ,不過不用管,這是這個 JWT 第三方工具包用來控制過期時間用的兩個屬性。

捕獲解析 JWT 失敗后產生的錯誤

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/10877.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/10877.shtml
英文地址,請注明出處:http://en.pswp.cn/web/10877.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

第1章 信息系統綜合知識 1.4 IT戰略

第1章 信息系統綜合知識 1.4 IT戰略 1.4.1 IT戰略的內涵 IT戰略&#xff0c;是在診斷和評估企業信息化現狀的基礎上&#xff0c;制定和調整企業信息化的指導綱領&#xff0c;爭取企業以最合適的成本&#xff0c;去做最合適的信息化工作。 IT戰略制定步驟: 定方向:明確遠景…

設計模式——模板設計模式(Template Method)

模板設計-base 什么是模板&#xff1f; 舉個簡單的例子&#xff0c;以AABB的格式&#xff0c;寫出一個詞語&#xff0c;你可能會想到&#xff0c;明明白白&#xff0c;干干凈凈等&#xff0c; 這個AABB就是一個模板&#xff0c;對模板心中有了一個清晰的概念之后&#xff0c;…

docker————docker的安裝

目錄 docker的安裝 1、安裝yum-utils工具 2、安裝yum倉庫 3、安裝docker引擎 4、設置開機啟動&#xff0c;并立即啟動 5、測試 docker的安裝 docker的官網Docker Docs 我才用的linux版本是rocky&#xff0c;使用的是最小安裝 1、安裝yum-utils工具 [rootbogon yum.rep…

環境變量(全)

概念 環境變量(environment variables)一般是指在操作系統中用來指定操作系統運行環境的一些參數 如&#xff1a;我們在編寫C/C代碼的時候&#xff0c;在鏈接的時候&#xff0c;從來不知道我們的所鏈接的動態靜態庫在哪里&#xff0c;但是照樣可以鏈接成功&#xff0c;生成可執…

今日arXiv最熱NLP大模型論文:揭露大語言模型短板,北京大學提出事件推理測試基準

人工智能領域又一里程碑時刻&#xff01;北京大學、北京智源人工智能研究院等機構聯合推出大型事件推理評測基準 。這是首個同時在知識和推理層面全面評估大模型事件推理能力的數據集。 總所周知&#xff0c;事件推理需要豐富的事件知識和強大的推理能力&#xff0c;涉及多種推…

consul啟動Error_server_rejoin_age_max (168h0m0s) - consider wiping your data dir

consul 啟動報錯&#xff1a; consul[11880]: 2024-05-12T08:37:51.095-0400 [ERROR] agent: startup error: error"refusing to rejoin cluster because server has been offline for more than the configured server_rejoin_age_max (168h0m0s) - consider wiping you…

【GD32】02-ADC模擬數字轉換器

ADC 在電子和通信技術中&#xff0c;ADC&#xff08;模擬數字轉換器&#xff09;是一種將模擬信號轉換為數字信號的電子設備。這種轉換是電子系統中非常關鍵的一個環節&#xff0c;因為數字信號更易于處理、存儲和傳輸。ADC的工作原理通常包括采樣、保持、量化和編碼等步驟。采…

http協議 tomcat如何訪問資源 servlet理論介紹

tomcat介紹 bin是啟動命令&#xff1b; conf是配置&#xff0c;可以修改端口號&#xff1b; lib是依賴的jar包&#xff1b; logs是日志 webapps是重點&#xff0c;在這里新建我們自己的javaWeb項目 tomcat如何訪問資源 tomcat通過統一資源定位符&#xff08;URL&#xff09;來…

鄉村振興與農村基礎設施建設:加大農村基礎設施建設投入,提升農村公共服務水平,改善農民生產生活條件,構建宜居宜業的美麗鄉村

一、引言 鄉村振興是我國現代化進程中的重要戰略&#xff0c;而農村基礎設施建設則是鄉村振興的基石。隨著城市化進程的加快&#xff0c;農村基礎設施建設滯后的問題日益凸顯&#xff0c;成為制約鄉村發展的瓶頸。因此&#xff0c;加大農村基礎設施建設投入&#xff0c;提升農…

打造一套在線教育系統,如何在教育這個慢行業打造品牌?

品牌對于教育行業非常重要&#xff0c;很多從事教育行業的朋友一直想塑造屬于自己的品牌形象&#xff0c;但做起來卻沒那么容易。因為教育行業相對來說是一個慢行業&#xff0c;用戶必須看到效果才會認可&#xff0c;而教育的效果往往需要經過長期的學習才能看到。 我覺得&…

AI大模型探索之路-訓練篇21:Llama2微調實戰-LoRA技術微調步驟詳解

系列篇章&#x1f4a5; AI大模型探索之路-訓練篇1&#xff1a;大語言模型微調基礎認知 AI大模型探索之路-訓練篇2&#xff1a;大語言模型預訓練基礎認知 AI大模型探索之路-訓練篇3&#xff1a;大語言模型全景解讀 AI大模型探索之路-訓練篇4&#xff1a;大語言模型訓練數據集概…

華為OD機試 - 執行任務賺積分 - 動態規劃(Java 2024 C卷 100分)

華為OD機試 2024C卷題庫瘋狂收錄中,刷題點這里 專欄導讀 本專欄收錄于《華為OD機試(JAVA)真題(A卷+B卷+C卷)》。 刷的越多,抽中的概率越大,每一題都有詳細的答題思路、詳細的代碼注釋、樣例測試,發現新題目,隨時更新,全天CSDN在線答疑。 一、題目描述 現有 N 個任…

Gradle基礎學習(六) 認識任務Task

理解Gradle中的任務 Gradle的構建過程基于任務&#xff08;Task&#xff09;的概念&#xff0c;而每個任務都可以包含一個或多個動作&#xff08;Action&#xff09;。 任務是構建中執行的一些獨立的工作單元&#xff0c;例如編譯類、創建JAR、生成Javadoc或將存檔發布到倉庫…

4.5網安學習第四階段第五周回顧(個人學習記錄使用)

本周重點 ①部署域環境&#xff08;Win2008&#xff09; ②域組策略 ③域內信息收集 ④(重點)哈希傳遞攻擊PTH ⑤MS14-068 提權漏洞 ⑥黃金票據偽造 ⑦白銀票據偽造 ⑧ZeroLogon (CVE-2020-1472) 漏洞復現 本周主要內容 ①部署域環境&#xff08;Win2008&#xff09;…

【算法】滑動窗口——串聯所有單詞的子串

今天來以“滑動窗口”的思想來詳解一道比較困難的題目——串聯所有單詞的子串&#xff0c;有需要借鑒即可。 目錄 1.題目2.下面是示例代碼3.總結 1.題目 題目鏈接&#xff1a;LINK 這道題如果把每個字符串看成一個字母&#xff0c;就是另外一道中等難度的題目&#xff0c;即&…

對象,字符串的解構賦值

大家想了解更多&#xff0c;可以去看阮一峰的ECMAScript6(ES6)標準入門課程 對象 簡介 解構不僅可以用于數組&#xff0c;還可以用于對象。 let { foo, bar } { foo: aaa, bar: bbb }; foo // "aaa" bar // "bbb" 對象的解構與數組有一個重要的不同。…

[CAM_REQ_MGR_EVENT_MAX]高通6225平臺相機老化異常重啟

報錯log 相機老化出現20/7萬比例的老化異常重啟&#xff0c;具體報錯log入下 <4>[ 167.506585] [1970:01:02 18:52:26](0) [0:swapper/0]cam_v4l2_event_queue_notify_error: 251 callbacks suppressed 7 3339<6>[ 167.506602] [1970:01:02 18:52:26](0) [0:swap…

面試試題一

封裝&#xff08;Encapsulation&#xff09; 面試問題&#xff1a; 封裝在面向對象編程中扮演什么角色&#xff1f;如何在Java中實現封裝&#xff1f;有哪些最佳實踐可以幫助提高類的封裝性&#xff1f; 詳細答案&#xff1a; 封裝的角色&#xff1a; 封裝是面向對象編程的核…

CMake 的繼承關系

1. CMake如何確定繼承關系 在 CMake 中&#xff0c;父子關系是通過文件系統中的目錄結構來定義的。當你在一個目錄中創建一個 CMakeLists.txt 文件時&#xff0c;該目錄就被視為一個 CMake 項目的目錄&#xff0c;而該文件中的內容將被用于配置和構建該目錄中的項目。 當你在父…

不同路徑| 和 不同路徑||

不同路徑| 一個機器人位于一個 m x n 網格的左上角 &#xff08;起始點在下圖中標記為 “Start” &#xff09;。 機器人每次只能向下或者向右移動一步。機器人試圖達到網格的右下角&#xff08;在下圖中標記為 “Finish” &#xff09;。 問總共有多少條不同的路徑&#xf…