這幾天天天搞到這么晚,我看今天的內容看起不多啊,不知道為什么學著學著就到了這么晚,今天的內容還是有點多哈,有點自我矛盾了,再次一一道來,
1.
首先今天先看到路由的概念,什么叫做路由?
路由就是映射關系,在express中路由指的是客戶端請求和服務器處理函式的映射關系,路由有三部分組成:請求型別、請求url和處理函式,
app.get(url,callback)其實就跟我們前面所說的監聽事件一樣一一樣的,
const express = require('express')
const app = express()
app.get('/', (req, res) => {
res.send('收到get請求')
})
app.listen(80, () => console.log('express server running at http://127.0.0.1'))
這就是一個最簡單的路由,路由的匹配程序,每當一個請求到達服務器器后,需要先經過路由匹配,當請求型別和url匹配成功后才會呼叫后面的請求函式,、
用法
最簡單的用法就是像我們上面那樣直接掛在實體上,這也是不推薦的,因為一個請求就要掛一個很麻煩很繁瑣,
科學的方法應該是創建路由模塊,
分為五個步驟:
分別是創建路由js檔案、呼叫express.Router創建路由物件、掛載路由、向外匯出路有物件最后我們的入口檔案需要匯入,在通過app.use去注冊
// 1.匯入express const express = require('express') // 2.創建路由物件 const router = express.Router() // 3.掛載路由 // 3.1掛載路由獲取用戶的資訊 router.get('/user/:id', (req, res) => { res.send(req.params) }) // 3.2掛載路由接受用戶發送的請求 router.post('/post', (req, res) => { res.send('post成功') }) // 4.向外共享路由成員 module.exports = { express, router }
const express = require('./02模塊化路由')
const app = express.express()
// 注冊路由
app.use(express.router)
app.listen(80, () => console.log('express server running at http://127.0.0.1'))
這里說一下app.use昨天也看到了,他其實就是一個用來注冊全域中間件的,然后我們還可以為路由掛載前綴,也是通過app.use來添加方法同昨天基本一樣
2.
中間件
指的是業務流程的中間處理環節,
就是當客戶請求到達服務器后,可連續呼叫多個中間件對這個請求進行預處理,最后通過路由發送出來,
中間件的本質是一個函式根路有類似但是多了一個引數,next引數,
next是一個函式它的作用就是實作多個中間件連續呼叫的關鍵,把流轉關系轉給下一個中間件或者路由,每個中間件都有一個next一個轉下去轉到路由沒有了就回應給客戶端了,
2.1
我們先看到全域生效的中間件,意思就是客戶發起的任何請求,他都會觸發,直接通過app.use來注冊即可
const express = require('express')
const app = express()
// 中間件
const mw = function(req, res, next) {
// res.send('這是中間件環節')
console.log('這是中漸漸環節')
next()
}
// 通過app,use定義為全域生效的中間件
app.use(mw)
app.get('/user', (req, res) => {
res.send('這是get請求')
})
app.post('/post', (res, req) => {
res.send('這是一個post請求')
})
app.listen(80, () => {
console.log('http://127.0.0.1');
})
中間件的作用:
多個中間件共享同一個res和req,所以可以在上游的中間件定義好這些物件,下游直接用包括路由也可以用
怎么來定義多個全域中間件,直接通過app.use定義多個即可就像昨天所說的托管靜態資源,有多個目錄就注冊多個
2.2
區域中間件
不是用app.use只對部分的路由有效,路由 的引數規則 也發生了改變
const express = require('express')
const app = express()
const mw = function(req, res, next) {
req.time = Date.now()
next()
}
app.get('/', mw, (req, res) => {
res.send('區域生效' + req.time)
})
app.get('/user', (req, res) => res.send('沒有生效') + req.time)
app.listen(80, ()=> {
console.log('http://127.0.0.1');
})
定義多個區域中間件
寫多個函式過后在引數這里可以用逗號隔開,也可以直接寫一個陣列
有一個注意事項:就是一定要在路由之前去注冊中間件,不然路由執行完了誰還來執行中間件,
2.3
中間件的分類
①應用級別中間件
就是通過get、post、use系結到app上的中間件
②路由級別中間件
就是在我們剛才的路由模塊里面來穿插的一個中間件
③錯誤級別中間件
這個有點說法
它是專門用來捕獲錯誤資訊的而且形參變為了四個
他也是唯一一個卸載路由后面的中間件
const express = require('express')
const { rename } = require('fs')
const app = express()
app.get('/', (req, res) => {
// 1.人為拋出一個錯誤,一旦有錯后面的回應就不會執行了
throw new Error('服務器內部發生錯誤')
res.send('我不能執行出來')
})
// 2.錯誤中間件
app.use((err,req,res,next) => {
// 2.1向服務器列印錯誤
console.log(err.message);
// 2.2向客戶端發送錯誤
res.send(err.message)
// 這樣做 好處就是,前面如果發生了錯誤導致了整個服務器已經崩潰了,什么都執行不了了,這樣一來,就可以正常輸出錯誤資訊,正常執行后面代碼
})
app.listen(80, () => console.log('express server running at http://127.0.0.1'))
④內置中間件
三個內置的中間件分別是express.static這個已經說過了前面
express.json這是拿來決議json格式資料的
express.urlencoded這是拿來決議urlencoded格式資料的
后面兩個一般會配合req.body來拿請求體資料再給他們拿來決議了
const express = require('express')
const app = express()
// 注意這是中間件 所以必須配置到路由之前
app.use(express.json())
app.use(express.urlencoded({extended : false}))
app.post('/', (req, res) => {
// 通過req.body可以拿到請求體資料
// postman在測驗的時候選擇body里面的raw再把text選擇json就可以發送json資料了
console.log(req.body);
// 沒有決議之前對于json資料是undefined
})
// 測驗urlencoded資料體
// 這個資料體的格式是x-www-form-urlencoded
// 固定寫法
app.post('/user', (req, res) => {
// 沒決議前時空物件
console.log(req.body);
})
app.listen(80, () => console.log('express server running at http://127.0.0.1'))
⑤第三方中間件 直接npm安裝匯入通過app.use注冊即可使用
2.4
自定義中間件
這里做一個案例自定義一個類似于express.urlencoded功能的中間件可以決議請求體資料
const express = require('express')
const app = express()
// 4.利用node里面的一個內置模塊決議請求體資料,在node里面內置了一個querystring模塊是專門用來處理查詢字串的,這個模塊提供的
// parse()函式可以把查詢字串轉換為物件
const qs = require('querystring')
// 1.定義中間件
app.use((req, res, next) => {
// 2.監聽data事件,因為既然是服務器,那么肯定會接收到癩子客戶端的請求,如果有時候請求量過大,就會分批次傳給服務器資料,所以data事件可能觸發多次
// 就需要把每一次的資料最后拼接起來
let str = ''
req.on('data', chunk => {
str += chunk
})
// 3.req的end事件當請求體接收完畢會自動出發end事件可以在這里處理完整的請求體資料
req.on('end', () => {
console.log(str);
str = qs.parse(str)
console.log(str);
// 5.講解洗出來的物件給到req.body
req.body = str
next()
})
})
app.post('/', (req, res) => {
res.send(req.body)
})
app.listen(80, () => console.log('http://127.0.0.1'))
然后將自定義中間件進行了一個模塊化
// 4.利用node里面的一個內置模塊決議請求體資料,在node里面內置了一個querystring模塊是專門用來處理查詢字串的,這個模塊提供的 // parse()函式可以把查詢字串轉換為物件 const qs = require('querystring') // 因為別人匯入進來是直接注冊使用所以可以把app開服務器等一些多余的代碼省略就保存app.use里面的 const bodyParse = (req, res, next) => { // 2.監聽data事件,因為既然是服務器,那么肯定會接收到癩子客戶端的請求,如果有時候請求量過大,就會分批次傳給服務器資料,所以data事件可能觸發多次 // 就需要把每一次的資料最后拼接起來 let str = '' req.on('data', chunk => { str += chunk }) // 3.req的end事件當請求體接收完畢會自動出發end事件可以在這里處理完整的請求體資料 req.on('end', () => { console.log(str); str = qs.parse(str) console.log(str); // 5.講解洗出來的物件給到req.body req.body = str next() }) } module.exports = bodyParse
const bodyParse = require('./自定義中間件模塊化')
const express = require('express')
const app = express()
app.use(bodyParse)
app.post('/', (req, res) => {
// res.send('收到get請求')
console.log(req.body);
})
app.listen(80, () => console.log('express server running at http://127.0.0.1'))
3.
我們繼續看到用express來寫介面
分為了三個步驟
創建基本服務器、創建 api路由模塊、撰寫get介面
這是路由模塊
// 2.寫api路由模塊 就是將路由模塊化 因為那邊引入進來需要用use來注冊同時掛載api前綴 const express = require('express') const router = express.Router() // 3.撰寫get介面 router.get('/get', (req, res) => { // 3.1首先拿到用戶傳過來的資料 let data =https://www.cnblogs.com/heymar/archive/2022/04/14/ req.query // 3.2把資料發送給客戶端 res.send({ status : 0, // 0表示成功 1表示失敗 msg : 'get請求成功', data : data //把資料回傳給客戶端 }) }) // 4.撰寫post介面 router.post('/post', (req, res) => { // 4.1客戶端發過來的資料 let data =https://www.cnblogs.com/heymar/archive/2022/04/14/ req.body res.send({ status : 0, msg : 'post請求成功', data : data }) }) module.exports = router
其實主要就是通過req的那幾個屬性拿到資料后,再通過send方法發給客戶端,下面是入口檔案主要就是開啟服務器,然后決議下資料
// 1.創建基本web服務器 const express = require('express') const app = express() // 2.1匯入路由模塊 并掛載前綴 const router = require('./router') // 4.2注冊內置中間件 不然req.body決議不出來 app.use(express.urlencoded({extended : false})) // 5.cors解決跨域 const cors = require('cors') app.use(cors()) app.use('/api', router) app.listen(80, ()=> { console.log('http://127.0.0.1'); })
有些東西要把后面看了才知道哈我只是先拿上來了,
4.
cors和jsonp
我們剛才這個案例其實是有bug的,就是有跨域的問題,我們創建一個html檔案通過button來獲取資料這個時候就會因為協議不同而被同源策略組織,
我們前面也說過解決跨域一個是cors一個是jsonp,這里肯定不能用jsonp因為他只支持get,那么怎么來用cors呢?
直接三部曲安裝匯入加注冊就解決了跨域問題了,就這么簡單,
4.1
什么是cors
就是由一系列http回應頭組成,同源策略碰到這個頭就會解除限制,
cors一般是在服務器進行配置,客戶端不需要,
下面是一些了解性內容
回應頭部:
第一個res.setHeader(‘Access-Control-Allow-Orign’,‘http:wwwssss,聰明、’)
這是表示只允許后面這個網站的域來訪問,如果為*那就表示允許任何域來訪問了
第二個是前面的基礎上為Allow-Headers
我們的cors默認值只有9個請求頭如果超出了這個九個頭就必然失敗請求,在這個九個之外的可以通過這個代碼來添加上來
第三個前面的基礎上-Methods
cors默認只支持get post head 除此之外的需要用這個來設定,
4.2
現在不是了解內容了,
cors請求分類
大體上分為簡單請求和預檢請求,
什么叫做簡單請求
滿足兩個條件:
一個是請求方式在默認的三個之內,一個是http請求頭不能超過默認的九個
什么是預檢請求
三個條件達到其中一種都是
一個是請求頭在九個之外,一個是請求方式在三個之外,還有一個就是發送過來的資料是json資料
那么他們的區別是什么呢
很簡單,簡單請求只會發送一次請求,而預檢請求會發送兩次請求,為什么?
因為預檢請求會在服務器與客戶端正是連接之前,提前發一個option的請求作為預檢,看服務器能否跟這個格式的請求相連接,只有請求成功了才會開始正式請求,攜帶真實資料,
5.
今天最后一個內容jsonp介面
首先要注意一下,如果說已經配置了cors那么必須在配置cors之前去宣告jsonp介面,不然會錯亂的,
做這個介面之前我們先來回應一下jsonp的一個知識,首先它是來解決跨域的,我們通過script標簽把函式傳進來再去呼叫介面這種方式就叫jsonp
// 1.創建基本web服務器 const express = require('express') const app = express() // 2.1匯入路由模塊 并掛載前綴 const router = require('./router') // 4.2注冊內置中間件 不然req.body決議不出來 app.use(express.urlencoded({extended : false})) // 6.jsonp介面必須寫在coes之前 app.get('/api/jsonp', (req, res) => { // 6.1獲取回呼函式的名字 let fn = req.query.callback // 6.2定義你要發送回去的資料物件 let data = https://www.cnblogs.com/heymar/archive/2022/04/14/{name :'張三', age : 15} // 6.3模擬函式呼叫 let fnDiao = `${fn}(${JSON.stringify(data)})` // 6.4資料回傳回去 res.send(fnDiao) }) // 5.cors解決跨域 const cors = require('cors') const { json } = require('body-parser') app.use(cors()) app.use('/api', router) app.listen(80, ()=> { console.log('http://127.0.0.1'); })


轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/458244.html
標籤:其他
上一篇:空間轉換/影片
下一篇:初識前后端
