欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報激活碼778899分享:Node.js-1

柚子快報激活碼778899分享:Node.js-1

http://yzkb.51969.com/

Node.js 簡介

定義:Node.js 是一個跨平臺 JavaScript 運行環(huán)境,使開發(fā)者可以搭建服務(wù)器端的 JavaScript 應(yīng)用程序

為什么 Node.js 能執(zhí)行 JS 代碼:

Chrome 瀏覽器能執(zhí)行 JS 代碼,依靠的是內(nèi)核中的 V8引擎(即:C++程序)

Node.js 是基于 Chrome V8 引擎進行封裝的注意:Node.js 環(huán)境沒有 DOM 和 BOM 等內(nèi)容,但是它也有自己獨立的 API

模塊化

基本認(rèn)知

Node.js 中根據(jù)模塊來源不同,將模塊分為了3大類,分別是:

內(nèi)置模塊(內(nèi)置模塊是由 Node.js 官方提供的,例如fs、path、http等)自定義模塊(用戶創(chuàng)建的每一個 .js 文件,都是自定義模塊)第三方模塊(由第三方開發(fā)出來的模塊,并非官方提供的內(nèi)置模塊,也不是用戶創(chuàng)建的自定義模塊,使用前需要提前下載)

加載模塊

使用強大的 require() 方法,可以加載需要的內(nèi)置模塊、用戶自定義模塊、第三方模塊進行使用(注意:使用 require() 方法加載其他模塊時,會執(zhí)行被加載模塊中的代碼)

// 加載內(nèi)置模塊

const fs = require('fs')

// 加載用戶自定義的模塊

const myModule = require('./myModule.js')

// 加載第三方模塊

const moment = require('moment')

module 對象

module 對象

每個自定義的模塊中都有一個 module 對象,它里面存儲了和當(dāng)前模塊有關(guān)的信息(打印結(jié)果,如下所示)

Module {

id: '.',

path: 'E:\\Desktop\\jsProject',

exports: {},

filename: 'E:\\Desktop\\jsProject\\test.js',

loaded: false,

children: [],

paths: [

'E:\\Desktop\\jsProject\\node_modules',

'E:\\Desktop\\node_modules',

'E:\\node_modules'

]

}

module.exports 對象

在自定義模塊中,可以使用 module.exports 對象,將模塊內(nèi)的成員共享出去,供外界使用

外界用 require() 方法導(dǎo)入自定義模塊時,得到的就是 module.exports 所指向的對象

【myModule.js文件】

module.exports.username = 'Jack'

module.exports.sayHello = () => { console.log('Hello') }

【text.js文件】

const m = require('./myModule')

console.log(m) // { username: 'Jack', sayHello: [Function (anonymous)] }

模塊化規(guī)范

Node.js 遵循了 CommonJS 模塊化規(guī)范,CommonJS 規(guī)定了模塊的特性和各模塊之間如何相互依賴

CommonJS 規(guī)定:

每個模塊內(nèi)部,module 變量代表當(dāng)前模塊module 變量是一個對象,它的 exports 屬性(即:module.exports)是對外的接口加載某個模塊,其實是加載該模塊的 module.exports 屬性。require() 方法用于加載模塊

npm與包

基本介紹

Node.js 中的第三方模塊又叫做包npm 公司提供了一個包管理工具,名字叫做 Node Package Manager(簡稱 npm 包管理工具),這個工具隨著 Node.js 的安裝被一起安裝到了用戶的電腦上npm 包管理工具能夠從 https://registry.npmjs.org/ 服務(wù)器把用戶需要的包(第三方模塊)下載到本地使用可以在終端執(zhí)行 npm -v 命令,來查看自己電腦上所安裝的 npm 包管理工具的版本號如果有需要的話,可以從"全球最大的包共享平臺"搜索自己想要的包:https://www.npmjs.com/

npm 體驗

目標(biāo):通過npm包管理工具,下載 moment 包,并輸出格式化時間

在終端輸入npm命令,下載 moment 包

npm install moment

簡寫

npm i moment

指定版本號(不指定版本號,默認(rèn)安裝最新版本的包)

npm i moment@2.22.2

輸出格式化時間(詳細(xì)操作,自行查閱官方文檔)

// 1. 導(dǎo)入 moment 包

const moment = require('moment')

// 2. 使用包里面的方法

const dt = moment.format('YYYY-MM-DD HH:mm:ss')

console.log(dt) // 輸出格式化時間

注意事項

初次裝包完成后,在項目文件夾下多一個叫做 node_modules 的文件夾和 package-lock.json 的配置文件 node_modules 文件夾用來存放所有已安裝到項目中的包。require() 導(dǎo)入第三方包時,就是從這個目錄中查找并加載包 package-lock.json 配置文件用來記錄 node_modules 目錄下的每一個包的下載信息,例如包的名字、版本號、下載地址 注意:不要手動修改 node_modules 或 package-lock.json 文件中的任何代碼,npm 包管理工具會自動維護它們 npm i moment@2.22.2 中的版本號由三位數(shù)字組成

每一位數(shù)字所代表的含義:

第一位數(shù)字:大版本(例如:底層重構(gòu))

第二位數(shù)字:功能版本(例如:新功能的推出)

第三位數(shù)字:Bug修復(fù)版本(例如:修復(fù)某個Bug)

版本號提升的規(guī)則:

只要前面的版本號增長了,后面的版本號"歸零"

包管理配置文件

基本認(rèn)知

npm 規(guī)定,在項目根目錄中,必須提供一個叫做 package.json 的包管理配置文件。用來記錄與項目有關(guān)的一些配置信息,例如:

- 項目的名稱、版本號、描述等

- 項目中都用到了哪些包

- 哪些包只在開發(fā)期間會用到

- 哪些包在開發(fā)和部署時都需要用到

問題:

在多人協(xié)作時,第三方包的體積過大,不方便團隊成員之間共享項目源代碼

解決方案:

共享時剔除 node_modules 目錄,讓其他成員根據(jù) package.json 配置文件,自行下載第三方模塊(注意:今后在項目開發(fā)中,一定要把 node_modules 文件夾,添加到 .gitignore 忽略文件中)

快速創(chuàng)建

npm 包管理工具提供了一個快捷命令,可以在執(zhí)行命令時所處的目錄中,快速創(chuàng)建 package.json 配置文件該命令只能在英文的目錄下成功運行當(dāng)我們后續(xù)運行 npm install 命令去安裝其他的包時,npm 包管理工具會自動更新配置文件的信息,我們不需要手動修改它

npm init -y

一次性安裝所有包

執(zhí)行 npm install 命令時,npm 包管理工具會先自動讀取 package.json 配置文件中的 dependencies 節(jié)點讀取到記錄的所有依賴包名稱和版本號之后,npm 包管理工具會把這些包一次性下載到項目中

npm install

卸載包

命令執(zhí)行成功后,會把卸載的包,自動從 package.json 的 dependencies 中移除掉

npm uninstall 包的名稱

devDependencies 節(jié)點

如果某些包只在項目開發(fā)階段用到,在項目上線之后不會使用,建議把這些包記錄到 devDependencies 節(jié)點中

npm i 包的名稱 -D

或者

npm i 包的名稱 --save-dev

npm 鏡像源

# 查看當(dāng)前的下包鏡像源

npm config get registry

# 將下包的鏡像源切換成淘寶鏡像源

npm config set registry https://registry.npmmirror.com

# 檢查鏡像源是否下載成功

npm config get registry

Node.js 內(nèi)置模塊

fs 文件系統(tǒng)模塊

// 1. 導(dǎo)入 fs 模塊對象

const fs = require('fs')

// 2. 寫入文件

// 參數(shù)1:要寫入內(nèi)容的文件的存放路徑

// 參數(shù)2:表示要寫入的內(nèi)容

// 參數(shù)3:寫入的格式(默認(rèn)utf8)

// 參數(shù)3:回調(diào)函數(shù)

const info = 'Hello World'

fs.writeFile('./test.txt', info, 'utf8', function (err) {

if (err) console.log(`錯誤信息${err}`)

else console.log(`寫入數(shù)據(jù)成功(數(shù)據(jù)信息:${info})`)

// 3. 讀取文件

// 參數(shù)1:讀取文件的存放路徑

// 參數(shù)2:讀取文件時候采用的編碼格式(默認(rèn)utf8)

// 參數(shù)3:回調(diào)函數(shù),拿到讀取失敗和成功的結(jié)果

fs.readFile('./test.txt', 'utf8', (err, data) => {

if (err) console.log(`錯誤信息${err}`)

else console.log(`讀取數(shù)據(jù)成功(數(shù)據(jù)信息:${data.toString()})`) // data 是 buffer 16 進制數(shù)據(jù)流對象,需要轉(zhuǎn)換為字符串格式

})

})

path 路徑模塊

獲取當(dāng)前文件所處的目錄

// __dirname 表示獲取當(dāng)前文件所處的目錄(文件夾)

console.log(__dirname)

路徑拼接

// 導(dǎo)入 path 模塊

const path = require('path')

// 注意: ../會抵消前面的路徑

const pathStr = path.join('/a', '/b/c', '../', '/d', '/e')

console.log(pathStr) // 輸出路徑為:\a\b\d\e

獲取文件名、擴展名

// 導(dǎo)入 path 模塊

const path = require('path')

// 定義文件的"存放路徑"

const filePath = '/a/b/c/index.html'

// 從"存放路徑"中獲取文件名(包含擴展名部分)

const fileName1 = path.basename(filePath)

console.log(fileName1) // 輸出結(jié)果:index.html

// 從"存放路徑"中獲取文件名(不包含擴展名部分)

const fileName2 = path.basename(filePath, '.html')

console.log(fileName2) // 輸出結(jié)果:index

// 從"存放路徑"中獲取文件擴展名

const extName = path.extname(filePath)

console.log(extName) // 輸出結(jié)果:.html

http 模塊

// 1. 導(dǎo)入 http 模塊

const http = require('http')

const { resolve } = require('path')

// 2. 創(chuàng)建 web 服務(wù)器實例

const server = http.createServer()

// 3. 為服務(wù)器實例綁定 request 事件

// req 是請求對象,包含了與客戶端相關(guān)的數(shù)據(jù)和屬性

// res 是響應(yīng)對象

// res.end() 方法用于向客戶端發(fā)送指定的內(nèi)容,并結(jié)束本次請求的處理過程

server.on('request', (req, res) => {

// req.url 是客戶端請求的 URL 地址

const url = req.url

// req.method 是客戶端請求的 method 類型

const method = req.method

// 為了防止中文亂碼的問題,需要設(shè)置響應(yīng)頭

res.setHeader('Content-Type', 'text/html; charset=utf-8')

// res.end() 方法

res.end(`

您的請求方式為:${method} 請求

`)

})

// 4. 啟動服務(wù)器

server.listen(80, () => {

console.log('server running at http://127.0.0.1:80')

})

第三方 API 模塊

express

基本介紹

Express 是基于 Node.js 平臺的 Web 開發(fā)框架,專門用來創(chuàng)建 Web 服務(wù)器Express 本質(zhì)上就是一個第三方模塊,相較與 Node.js 內(nèi)置的 http 模塊,它使用起來更簡單,開發(fā)效率更高(Express 是基于 http 模塊進一步封裝出來的)Express 中文官網(wǎng):https://www.expressjs.com.cn/

模塊使用

安裝

npm i express@4.17.1

創(chuàng)建 Web 服務(wù)器

// 1. 導(dǎo)入 express

const express = require('express')

// 2. 創(chuàng)建 web 服務(wù)器

const app = express()

// 4. 監(jiān)聽客戶端的 GET 和 POST 請求

// GET app.get('請求URL', (請求對象, 響應(yīng)對象) => { 處理函數(shù) })

// POST app.post('請求URL', (請求對象, 響應(yīng)對象) => { 處理函數(shù) })

app.get('/user', (req, res) => {

res.send({ name: 'Jack', age: 20, gender: '男' }) // 響應(yīng)一個 JSON 對象

})

app.post('/user', (req, res) => {

res.send('訂單提交成功,請等待商家發(fā)貨') // 響應(yīng)

})

// 5. 獲取URL攜帶的查詢參數(shù)

app.get('/', (req, res) => {

// 默認(rèn)情況下,req.query 是一個空對象

// 查詢參數(shù) ?name=Jack&age=20

// 可通過 req.query.name 與 req.query.age 獲得其值

console.log(req.query)

res.send(req.query)

})

// 6. 獲取URL中的動態(tài)參數(shù)

app.get('/user/:id/:name', (req, res) => {

// req.params 默認(rèn)是一個空對象,里面存放著,通過冒號識別出來的參數(shù)值

res.send(req.params)

})

// 3. 調(diào)用 app.listen(端口號, 啟動成功后的回調(diào)函數(shù))

app.listen(80, () => {

console.log('Server started successfully at http://127.0.0.1/')

})

托管靜態(tài)資源

認(rèn)識 express.static()

介紹:

express 提供了一個非常好用的函數(shù),叫做 express.static()

通過它,我們可以非常方便地創(chuàng)建一個靜態(tài)資源服務(wù)器

例如:

項目目錄下有一個 public 文件夾,里面存放了圖片、html、css、js文件,通過下面的代碼就可以將它們對外開放訪問了

注意:

express 在指定的靜態(tài)文件中查找文件,并對外提供資源的訪問路徑,因此,存放靜態(tài)文件的目錄名(本例中為public)是不會出現(xiàn)在URL中的

http://127.0.0.1/images/img0.jpg

http://127.0.0.1/html/index.html

http://127.0.0.1/css/index.css

http://127.0.0.1/js/index.js

app.use(express.static('public'))

托管多個靜態(tài)資源目錄

app.use(express.static('public'))

app.use(express.static('files'))

......

掛載路徑前綴

如果希望在托管的靜態(tài)資源訪問路徑之前,掛載路徑前綴,可以使用下面的代碼

http://127.0.0.1/public/images/img0.jpg

http://127.0.0.1/public/html/index.html

http://127.0.0.1/public/css/index.css

http://127.0.0.1/public/js/index.js

app.use('public', express.static('public'))

nodemon

為什么要使用 nodemon

在編寫調(diào)試 Node.js 項目的時候,如果修改了項目的代碼,則需要頻繁的手動 close 掉,然后再重新啟動,非常繁瑣

為了解決這個問題,我們可以使用 nodemon 這個工具,它能夠監(jiān)聽項目文件的變動,當(dāng)代碼修改后,nodemon 會自動幫我們重啟項目,極大方便了開發(fā)和調(diào)試

安裝 nodemon

在終端中運行下面命令,即可將 nodemon 安裝為全局可用的工具

npm install -g nodemon

使用 nodemon

nodemon 要執(zhí)行的js文件的路徑

例如:nodemon E:\Desktop\jsProject\test.js

路由

直接掛載路由

const express = require('express')

const app = express()

// 直接在app上掛載路由

app.get('/', (req, res) => { res.send('this is get') })

app.post('/', (req, res) => { res.send('this is post') })

app.listen(80, () => {

console.log('Server is running at http://127.0.0.1/')

})

模塊化的方式,掛載路由,實現(xiàn)解耦合

文件名:routerModule

// 這是路由模塊

// 1. 導(dǎo)入 express 模塊

const express = require('express')

// 2. 創(chuàng)建路由對象

const router = express.Router()

// 3. 掛載具體的路由

router.get('/list', (req, res) => { res.send('Get user list.') })

router.post('/add', (req, res) => { res.send('Add new user.') })

// 4. 向外導(dǎo)出路由對象

module.exports = router

文件名:myApplication

// 這是 app (application-應(yīng)用)

// 1. 導(dǎo)入 express 模塊

const express = require('express')

// 2. 創(chuàng)建應(yīng)用

const app = express()

// 4. 導(dǎo)入路由模塊

const router = require('./routerModule')

// 5. "注冊"路由模塊

app.use('/user', router)

// app.use(express.static('public'))

// 注意:app.use() 函數(shù)的作用,就是用來"注冊"全局中間件

// 3. 運行服務(wù)器,監(jiān)聽?wèi)?yīng)用的80端口

app.listen(80, () => { console.log('Server is running at http://127.0.0.1/') })

中間鍵

基本認(rèn)識

// 1. 導(dǎo)入 express 模塊

const express = require('express')

// 2. 創(chuàng)建應(yīng)用

const app = express()

// 4. 定義一個中間件函數(shù)

const mw = (req, res, next) => {

console.log('這是最簡單的中間件函數(shù)')

next() // 把流轉(zhuǎn)關(guān)系,轉(zhuǎn)交給下一個中間件或路由

}

// 5. 將 mw 注冊為全局生效的中間件

// 當(dāng)注冊成功后,用戶每次請求服務(wù)時,都會先執(zhí)行中間鍵函數(shù)里面的內(nèi)容,再執(zhí)行路由函數(shù)里面的內(nèi)容

app.use(mw)

// 6. 創(chuàng)建路由

app.get('/', (req, res) => { res.send('home page') })

app.get('/user', (req, res) => { res.send('user page') })

// 3. 運行服務(wù)器,監(jiān)聽?wèi)?yīng)用的80端口

app.listen(80, () => { console.log('Server is running at http://127.0.0.1/') })

體驗它的作用

// 1. 導(dǎo)入 express 模塊

const express = require('express')

// 2. 創(chuàng)建應(yīng)用

const app = express()

// 4. 注冊全局中間件

app.use((req, res, next) => {

// 獲取請求到達服務(wù)器的時間

const time = Date.now()

// 為req對象,掛載自定義屬性,從而把時間共享給后面的所有路由

req.startTime = time

next()

})

// 5. 創(chuàng)建路由

app.get('/', (req, res) => { res.send('home page ' + req.startTime) })

app.get('/user', (req, res) => { res.send('user page ' + req.startTime) })

// 3. 運行服務(wù)器,監(jiān)聽?wèi)?yīng)用的80端口

app.listen(80, () => { console.log('Server is running at http://127.0.0.1/') })

定義多個全局中間件

// 1. 導(dǎo)入 express 模塊

const express = require('express')

// 2. 創(chuàng)建應(yīng)用

const app = express()

// 4. 注冊全局中間件

// 4.1 注冊第一個中間件

app.use((req, res, next) => {

console.log('調(diào)用了第1個中間件')

next()

})

// 4.2 注冊第二個中間件

app.use((req, res, next) => {

console.log('調(diào)用了第2個中間件')

next()

})

// 4.3 注冊第三個中間件

app.use((req, res, next) => {

console.log('調(diào)用了第3個中間件')

next()

})

// 5. 創(chuàng)建路由

app.get('/user', (req, res) => { res.send('user page') })

// 3. 運行服務(wù)器,監(jiān)聽?wèi)?yīng)用的80端口

app.listen(80, () => { console.log('Server is running at http://127.0.0.1/') })

局部生效的中間件

// 1. 導(dǎo)入 express 模塊

const express = require('express')

// 2. 創(chuàng)建應(yīng)用

const app = express()

// 4. 定義一個中間件函數(shù)

const mw = (req, res, next) => {

console.log('調(diào)用了局部生效的中間件')

next()

}

// 5. 創(chuàng)建路由

app.get('/', mw, (req, res) => { res.send('home page') }) // 使用了局部中間件

app.get('/user', (req, res) => { res.send('user page') }) // 沒有使用局部中間件

// 3. 運行服務(wù)器,監(jiān)聽?wèi)?yīng)用的80端口

app.listen(80, () => { console.log('Server is running at http://127.0.0.1/') })

定義多個局部中間件

// 以下兩種寫法是等效的

app.get('/', mw1, mw2, (req, res)=>{ res.send('home page') })

app.get('/', [mw1, mw2], (req, res)=>{ res.send('home page') })

錯誤級別的中間件

// 1. 導(dǎo)入 express 模塊

const express = require('express')

// 2. 創(chuàng)建應(yīng)用

const app = express()

// 4. 定義路由

app.get('/', (req, res) => {

throw new Error('The Error made by People.') // 人為制造錯誤

res.send('home page') // 此處無法執(zhí)行

})

// 5. 定義錯誤級別的中間件,捕獲整個項目的異常錯誤,從而防止程序的崩潰

app.use((err, req, res, next) => {

console.log('警告!服務(wù)器發(fā)生了錯誤。\n錯誤信息:' + err.message)

res.send('尊敬的用戶,很抱歉,服務(wù)器出錯了~')

}) // 錯誤級別的中間件一定要放在所有路由之后

// 3. 運行服務(wù)器,監(jiān)聽?wèi)?yīng)用的80端口

app.listen(80, () => { console.log('Server is running at http://127.0.0.1/') })

express 內(nèi)置的中間件

自從 Express 4.16.0 版本開始,Express 內(nèi)置了3個常用的中間件,極大的提高了 Express 項目的開發(fā)效率和體驗

1. express.static 快速托管靜態(tài)資源的內(nèi)置中間件,例如:HTML文件、CSS樣式、圖片等

2. express.json 解析 JSON 格式的請求體數(shù)據(jù) (4.16.0+ 版本可用)

3. express.urlencoded 解析 URL-encoded 格式的請求體數(shù)據(jù) (4.16.0+ 版本可用)

// 1. 導(dǎo)入 express 模塊

const express = require('express')

// 2. 創(chuàng)建應(yīng)用

const app = express()

// 4.1 通過express.json()這個中間件,解析表單中的JSON

app.use(express.json())

// 4.2 通過express.urlencoded()這個中間件,來解析表單中的url-encoded格式的數(shù)據(jù)

app.use(express.urlencoded({ extended: false }))

// 5. 創(chuàng)建路由

app.post('/user', (req, res) => {

// 使用 req.body 屬性,可用接收客戶端發(fā)送過來的請求體數(shù)據(jù)

// 默認(rèn)情況下,如果不配置解析表單數(shù)據(jù)的中間件,則 req.body 默認(rèn)等于 undefined

console.log(req.body)

res.send('ok')

})

app.post('/book', (req, res) => {

// 在服務(wù)器端,可用通過 req.body 來獲取 JSON 格式的表單數(shù)據(jù)和 url-encoded 格式的數(shù)據(jù)

console.log(req.body)

res.send('ok')

})

// 3. 運行服務(wù)器,監(jiān)聽?wèi)?yīng)用的80端口

app.listen(80, () => { console.log('Server is running at http://127.0.0.1/') })

跨域訪問

下載并安裝 cors 中間件

npm i cors@2.8.5

使用 cors 中間件

// 導(dǎo)入 cors 中間件

const cors = require('cors')

// 將 cors 注冊為全局中間件

app.use(cors())

跨域資源共享

點擊鏈接:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS

mysql

基本內(nèi)容

安裝

npm install mysql

配置

// 1. 導(dǎo)入 mysql 模塊

const mysql = require('mysql')

// 2. 建立與 MySQL 數(shù)據(jù)庫的連接

const db = mysql.createPool({

host: '127.0.0.1', // 數(shù)據(jù)庫的IP地址

user: 'root', // 登錄數(shù)據(jù)庫的賬號

password: 'admin123', // 登錄數(shù)據(jù)庫的密碼

database: 'myDatabase' // 指定要操作哪個數(shù)據(jù)庫

})

測試

// 檢測 mysql 模塊能否正常工作

db.query('select 1', (err, results) => {

if (err) return console.log(err.message) // mysql 模塊工作期間報錯了

console.log(results) // 能夠成功的執(zhí)行SQL語句

})

查詢與插入數(shù)據(jù)

查詢數(shù)據(jù)

// 1. 導(dǎo)入 mysql 模塊

const mysql = require('mysql')

// 2. 建立與 MySQL 數(shù)據(jù)庫的連接

const db = mysql.createPool({

host: '127.0.0.1', // 數(shù)據(jù)庫的IP地址

user: 'root', // 登錄數(shù)據(jù)庫的賬號

password: 'admin123', // 登錄數(shù)據(jù)庫的密碼

database: 'myDatabase' // 指定要操作哪個數(shù)據(jù)庫

})

// 3. 查詢 users 表中所有的數(shù)據(jù)

const sqlStr = 'select * from users'

db.query(sqlStr, (err, results) => {

// 查詢數(shù)據(jù)失敗

if (err) return console.log(err.message)

// 查詢數(shù)據(jù)成功

console.log(results)

})

插入數(shù)據(jù)

// 1. 導(dǎo)入 mysql 模塊

const mysql = require('mysql')

// 2. 建立與 MySQL 數(shù)據(jù)庫的連接

const db = mysql.createPool({

host: '127.0.0.1', // 數(shù)據(jù)庫的IP地址

user: 'root', // 登錄數(shù)據(jù)庫的賬號

password: 'admin123', // 登錄數(shù)據(jù)庫的密碼

database: 'myDatabase' // 指定要操作哪個數(shù)據(jù)庫

})

// 3. 向 users 表中插入數(shù)據(jù)

const user = { username: 'Jack', password: '123456' }

const sqlStr = 'insert into users set ?'

db.query(sqlStr, user, (err, results) => {

if (err) return console.log(err.message) // 執(zhí)行SQL語句失敗了

if (results.affectedRows === 1) { console.log('插入數(shù)據(jù)成功!') }

})

更新與刪除數(shù)據(jù)

更新數(shù)據(jù)

// 1. 導(dǎo)入 mysql 模塊

const mysql = require('mysql')

// 2. 建立與 MySQL 數(shù)據(jù)庫的連接

const db = mysql.createPool({

host: '127.0.0.1', // 數(shù)據(jù)庫的IP地址

user: 'root', // 登錄數(shù)據(jù)庫的賬號

password: 'admin123', // 登錄數(shù)據(jù)庫的密碼

database: 'myDatabase' // 指定要操作哪個數(shù)據(jù)庫

})

// 3. 更新 users 表中數(shù)據(jù)

const user = { id: 6, username: 'Jack', password: '123456' }

const sqlStr = 'update users set ? where id=?'

db.query(sqlStr, [user, user.id], (err, results) => {

if (err) return console.log(err.message) // 執(zhí)行SQL語句失敗了

if (results.affectedRows === 1) { console.log('更新數(shù)據(jù)成功!') }

})

刪除數(shù)據(jù)

// 1. 導(dǎo)入 mysql 模塊

const mysql = require('mysql')

// 2. 建立與 MySQL 數(shù)據(jù)庫的連接

const db = mysql.createPool({

host: '127.0.0.1', // 數(shù)據(jù)庫的IP地址

user: 'root', // 登錄數(shù)據(jù)庫的賬號

password: 'admin123', // 登錄數(shù)據(jù)庫的密碼

database: 'myDatabase' // 指定要操作哪個數(shù)據(jù)庫

})

// 3. 刪除 users 表中的數(shù)據(jù)(刪除id=5的用戶數(shù)據(jù))

const sqlStr = 'delete from users where id=?'

db.query(sqlStr, 5, (err, results) => {

if (err) return console.log(err.message) // 執(zhí)行SQL語句失敗了

if (results.affectedRows === 1) { console.log('刪除數(shù)據(jù)成功!') }

})

標(biāo)記刪除法:(擴展)

使用 delete 語句,是真的會把數(shù)據(jù)從表中抹除掉。為了保險起見,推薦使用標(biāo)記刪除法,來模擬刪除的動作。

什么是標(biāo)記刪除法呢?就是在創(chuàng)建表的時候,提前建立好一個 status 狀態(tài)字段,用來表示當(dāng)前這條數(shù)據(jù)是否被刪除掉,當(dāng)我們使用標(biāo)記刪除法后,哪怕用戶刪除數(shù)據(jù)了,有一天用戶需要找回來,也能找到這條數(shù)據(jù)。

Web 開發(fā)模式

目前主流的開發(fā)模式有兩種

基于服務(wù)端渲染的傳統(tǒng) Web 開發(fā)模式基于前后端分離的新型 Web 開發(fā)模式

服務(wù)端渲染

概念

服務(wù)端發(fā)送給客戶端的HTML頁面,是在服務(wù)器通過字符串的拼接,動態(tài)生成的。因此,客戶端不需要使用Ajax這樣的技術(shù)額外請求頁面的數(shù)據(jù)。

優(yōu)點

前端耗時少(因為服務(wù)器端負(fù)責(zé)動態(tài)生成HTML內(nèi)容,瀏覽器只需要直接渲染即可,尤其是移動端,更省電)有利于SEO(因為服務(wù)器端響應(yīng)的是完整的HTML頁面內(nèi)容,所以爬蟲更容易獲取信息,更有利于SEO)

缺點

占用服務(wù)器資源(服務(wù)器端完成HTML頁面內(nèi)容的拼接,如果請求較多,會對服務(wù)器造成一定的訪問壓力)不利于前后端分離,開發(fā)效率低(使用服務(wù)器端渲染,則無法分工合作,尤其對于前端項目復(fù)雜度高的項目,不利于項目高效開發(fā))

前后端分離

概念

前后端分離的開發(fā)模式,依賴于Ajax技術(shù)的廣泛應(yīng)用。簡而言之,前后端分離的Web開發(fā)模式,就是后端只負(fù)責(zé)提供API接口,前端使用Ajax調(diào)用接口的開發(fā)模式。

優(yōu)點

開發(fā)體驗好。(前端專注于 UI 頁面的開發(fā),后端專注于 API 的開發(fā),而且前端有更多的選擇性)用戶體驗好。(Ajax 技術(shù)的廣泛應(yīng)用,極大的提高了用戶的體驗 ,可以輕松實現(xiàn)頁面的局部刷新)減輕了服務(wù)器的壓力(頁面最終是在每個用戶的瀏覽器中生成的)

缺點

不利于 SEO (因為完整的HTML頁面需要在客戶端動態(tài)拼接完成,所以爬蟲難以爬取頁面的有效信息)

解決方案:

利用 Vue、React 等前端框架的 SSR (server side render) 技術(shù)能夠很好的解決 SEO 問題

身份認(rèn)證

基本認(rèn)識

介紹:

身份認(rèn)證(Authoritarian)又稱"身份驗證"、"鑒權(quán)",它是指通過一定的手段,完成對用戶身份的確認(rèn)

例如:

手機驗證碼登錄、郵箱密碼登錄、二維碼登錄等

不同開發(fā)模式下的身份認(rèn)證

1.服務(wù)端渲染推薦使用 Session 認(rèn)證機制

2.前后端分離推薦使用 JWT 認(rèn)證機制

Session 認(rèn)證機制

Cookie

HTTP 無狀態(tài)性質(zhì)

HTTP 協(xié)議的無狀態(tài)性質(zhì),指的是客戶端每次的 HTTP 請求都是獨立的,連續(xù)多個請求之前沒有直接的關(guān)系,服務(wù)器不會主動保留每次 HTTP 請求的狀態(tài)

突破 HTTP 無狀態(tài)的限制

使用 Cookie 可以彌補 HTTP 無法記錄狀態(tài)的問題

什么是 Cookie

Cookie 是存儲在用戶瀏覽器中的一段不超過 4KB 的字符串

它由一個名稱(Name)、一個值(value)和其他幾個用于控罪 Cookie 有效期、安全性、使用范圍的可選屬性組成

不同域名下的 Cookie 各自獨立,每當(dāng)客戶端發(fā)起請求時,會自動把當(dāng)前域名下所有未過期的 Cookie 一同發(fā)送到服務(wù)器

Cookie 的幾大特性

1.自動發(fā)送

2.域名獨立

3.過期時限

4.4KB限制

Cookie 在身份認(rèn)證中的作用

客戶端第一次請求服務(wù)器的時候,服務(wù)器通過響應(yīng)頭的形式,向客戶端發(fā)送一個身份認(rèn)證的 Cookie,客戶端會自動將 Cookie 保存在瀏覽器中

隨后,當(dāng)客戶端瀏覽器每次請求服務(wù)器的時候,瀏覽器會自動將身份認(rèn)證相關(guān)的 Cookie,通過請求頭的形式發(fā)送給服務(wù)器,服務(wù)器即可驗證客戶端的身份

Cookie 不具有安全性

由于 Cookie 是存儲在瀏覽器中的,而且瀏覽器也提供了讀寫 Cookie 的 API,因此 Cookie 很容易被偽造,不具有安全性。因此不建議服務(wù)器將重要的隱私數(shù)據(jù),通過 Cookie 的形式發(fā)送給瀏覽器

Session

Session = Cookie + 認(rèn)證Session 的工作原理

實現(xiàn) Session 認(rèn)證

安裝 express-session 中間件

npm install express-session

配置 express-session 中間件

// 1. 導(dǎo)入 session 中間件

const session = require('express-session')

// 2. 配置 Session 中間件

app.use(session({

secret: 'keyboard cat', // secret 屬性的值可以為任意字符串

resave: false, // 固定寫法

saveUninitialized: true // 固定寫法

}))

session 操作

當(dāng) express-session 中間件配置成功后,即可通過 req.session 來訪問和使用 session 對象,從而存儲用戶的關(guān)鍵信息

// 1. 創(chuàng)建服務(wù)器實例

const express = require('express')

const app = express()

// 3. 配置 express-session 中間件

const session = require('express-session')

app.use(session({

secret: 'keyboard cat', // secret 屬性的值可以為任意字符串

resave: false, // 固定寫法

saveUninitialized: true // 固定寫法

}))

// 4. 創(chuàng)建路由

// 4.1 登錄接口

app.post('api/login', (req, res) => {

// 判斷用戶提交的登錄信息是否正確

if (req.body.username !== 'admin' || req.body.password !== '123456') {

return res.send({ status: 1, msg: '登錄失敗' })

}

req.session.user = req.body // 將用戶的信息,存儲到 Session 中

req.session.isLogin = true // 將用戶的登錄狀態(tài),存儲到 Session 中

req.send({ status: 0, msg: '登錄成功' })

})

// 4.2 獲取用戶姓名的接口

app.get('/api/username', (req, res) => {

// 從 Session 中獲取用戶的名稱,響應(yīng)給客戶端

if (!req.session.isLogin) {

return res.send({ status: 1, msg: 'fail' })

}

res.send({

status: 0,

msg: 'success',

username: req.session.user.username

})

})

// 4.3 退出登錄的接口

app.post('/api/logout', (req, res) => {

// 清空當(dāng)前客戶端對應(yīng)的 Session 信息

req.session.destory()

res.send({

status: 0,

msg: '退出登錄成功'

})

})

// 2. 啟動服務(wù)器

app.listen(80, (req, res) => {

console.log('Server is running at http://127.0.0.1/')

})

Session 認(rèn)證的局限性

Session 認(rèn)證機制需要配合 Cookie 才能實現(xiàn)。

由于 Cookie 默認(rèn)不支持跨域訪問,所以,當(dāng)涉及到前端跨域請求后端接口時,需要做很多額外配置,才能實現(xiàn)跨域 Session 認(rèn)證

當(dāng)前端請求后端接口不存在跨域問題的時候,推薦使用 Session 身份認(rèn)證機制

當(dāng)前端需要跨域請求后端接口的時候,不推薦使用 Session 身份認(rèn)證機制,推薦使用 JWT 認(rèn)證機制

JWT 認(rèn)證機制

簡介

JWT(JSON Web Token)是目前最流行的跨域認(rèn)證解決方案工作原理

**JWT **通常由三部分組成

Header (頭部)

Payload (有效載荷)

Signature (簽名)

三者之間使用英文的"."進行分隔

Payload 部分才是真正的用戶信息,它是用戶信息經(jīng)過加密之后生成的字符串

Header 和 Signature 是安全性相關(guān)的部分,只是為了保證 Token 的安全性

JWT 的使用方式

客戶端收到服務(wù)器返回的 JWT 之后,通常會將它存儲在 localStorage 或 sessionStorage 中

此后,客戶端每次與服務(wù)器通信,都要帶上這個 JWT 的字符串,從而進行身份認(rèn)證

推薦的做法是把 JWT 放在 HTTP 請求頭的 Authoritarian 字段中

格式如下:

Authorization: Bearer

實現(xiàn) JWT 認(rèn)證

安裝 JWT 相關(guān)的包

jsonwebtoken 用于生成 JWT 字符串

express-jwt 用于將 JWT 字符串解析還原成 JSON 對象

npm install jsonwebtoken express-jwt

使用 JWT

// 1. 創(chuàng)建服務(wù)器實例

const express = require('express')

const app = express()

// 3. 使用 JWT

// 3.1 安裝并導(dǎo)入 JWT 相關(guān)的兩個包

const jwt = require('jsonwebtoken')

const expressJWT = require('express-jwt')

// 3.2 設(shè)置 secret 密鑰,保證 JWT 字符串的安全

const secretKey = 'text use ^_^'

// 3.4 將 JWT 字符串解析還原成 JSON 對象

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

const mw = expressJWT({ secret: secretKey }).unless({ path: [/^\/api\//] })

app.use(mw) // 將這個中間件注冊為全局中間件

// 獲取用戶信息的接口

app.get('/admin/getInfo', (req, res) => {

// 3.5 使用 req.user 獲取用戶信息,并使用 data 屬性將用戶信息發(fā)送給客戶端

console.log(req.user)

res.send({

status: 200,

message: "獲取用戶信息成功",

data: req.user

})

})

// 登錄接口

app.post('api/login', (req, res) => {

const userinfo = req.body

// 登錄失敗

if (userinfo.username !== 'admin' || userinfo.password !== '123456') {

return res.send({ status: 400, message: '登錄失敗' })

}

// 登錄成功

// 3.3 登錄成功后,生成 JWT 字符串,并通過 token 屬性發(fā)送給客戶端

// 參數(shù)1:用戶的信息對象

// 參數(shù)2:加密的密鑰

// 參數(shù)3:配置對象,可以配置當(dāng)前的 token 的有效期

const tokenStr = jwt.sign({ username: userinfo.username }, secretKey, { expiresIn: '60s' })

req.send({ status: 200, message: '登錄成功', token: tokenStr })

})

// 3.6 使用全局錯誤處理中間件,捕獲解析 JWT 失敗后產(chǎn)生的錯誤

app.use((err, req, res) => {

// 判斷錯誤是否為 token 解析失敗導(dǎo)致

if (err.name === 'UnauthorizedError') return res.send({ status: 401, message: '無效的token' })

res.send({ status: 500, message: '未知的錯誤' })

})

// 2. 啟動服務(wù)器

app.listen(80, (req, res) => {

console.log('Server is running at http://127.0.0.1/')

})

柚子快報激活碼778899分享:Node.js-1

http://yzkb.51969.com/

參考閱讀

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://m.gantiao.com.cn/post/18959193.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機訪問

文章目錄