1. Express框架是什麼 1.1 Express是一個基於Node平臺的web應用開發框架,它提供了一系列的強大特性,幫助你創建各種Web應用。我們可以使用 npm install express 命令進行下載。 1.2 Express初體驗 // 引入express框架 const expr ...
1. Express框架是什麼
1.1 Express是一個基於Node平臺的web應用開發框架,它提供了一系列的強大特性,幫助你創建各種Web應用。我們可以使用 npm install express 命令進行下載。
1.2 Express初體驗
// 引入express框架 const express = require('express'); // 創建網站伺服器 const app = express(); app.get('/' , (req, res) => { // send() // 1. send方法內部會檢測響應內容的類型 // 2. send方法會自動設置http狀態碼 // 3. send方法會幫我們自動設置響應的內容類型及編碼 res.send('Hello. Express'); }) app.get('/list', (req, res) => { res.send({name: '張三', age: 20}) }) // 監聽埠 app.listen(3000); console.log('網站伺服器啟動成功');
2. 中間件
2.1 什麼是中間件
中間件就是express框架提供的一堆方法,可以接收客戶端發來的請求、可以對請求做出響應,也可以將請求繼續交給下一個中間件繼續處理,即接受請求,處理請求。
中間件主要由兩部分構成,中間件方法以及請求處理函數。
中間件方法由Express提供,負責攔截請求,請求處理函數由開發人員提供,負責處理請求。
//中間件示例 app.get('請求路徑', '處理函數') // 接收並處理get請求 app.post('請求路徑', '處理函數') // 接收並處理post請求
可以針對同一個請求設置多個中間件,對同一個請求進行多次處理。
預設情況下,請求從上到下依次匹配中間件,一旦匹配成功,終止匹配。
可以調用next方法將請求的控制權交給下一個中間件,直到遇到結束請求的中間件。
//02.中間件.js //引入express框架 const express = require("express"); //創建網站伺服器 const app = express(); //當客戶端以get方式訪問/request路由時 //第一個中間件 app.get('/request', (req, res, next) => { req.name = "張三"; next(); }); //下一個中間件 app.get('/request', (req, res) => { res.send(req.name); }); //監聽埠 app.listen(3000);
2.2 app.use中間件用法
app.use 匹配所有的請求方式,可以直接傳入請求處理函數,代表接收所有的請求。
app.use((req, res, next) => { console.log(req.url); next(); });
app.use 第一個參數也可以傳入請求地址,代表不論什麼請求方式,只要是這個請求地址就接收這個請求。
app.use('/request', (req, res, next) => {
console.log(req.url);
next();
});
- 輸入
http://localhost:3000
,控制台列印請求走了app.use中間件
- 輸入
http://localhost:3000/request
,控制台列印請求走了app.use中間件、請求走了app.use /request中間件
//03.app.use.js const express = require("express"); const app = express(); //接受所有請求的中間件 app.use((req, res, next) => { console.log('請求走了app.use中間件'); next() }) //當客戶端訪問/request請求時走當前中間件 app.use('/request', (req, res, next) => { console.log('請求走了app.use /request中間件'); next(); }); app.get('/list', (req, res) => { res.send('/list'); }); //監聽埠 app.listen(3000);
2.3 中間件應用
1.網站維護公告 ,寫在最前面,直接為客戶端做出響應,網站正在維護中。
// 引入express框架 const express = require('express'); // 創建網站伺服器 const app = express(); app.use((req, res, next) => { res.send('當前網站正在維護...') })
2.路由保護,客戶端在訪問需要登錄的頁面時,可以先使用中間件判斷用戶登錄狀態,用戶如果未登錄,則攔截請求,直接響應,禁止用戶進入需要登錄的頁面。
app.use('/admin', (req, res, next) => { // 用戶沒有登錄 let isLogin = true; // 如果用戶登錄 if (isLogin) { // 讓請求繼續向下執行 next() }else { // 如果用戶沒有登錄 直接對客戶端做出響應 res.send('您還沒有登錄 不能訪問/admin這個頁面') } }) app.get('/admin', (req, res) => { res.send('您已經登錄 可以訪問當前頁面') })
3.自定義404頁面
app.use((req, res, next) => { // 為客戶端響應404狀態碼以及提示信息 res.status(404).send('當前訪問的頁面是不存在的') }) // 監聽埠 app.listen(3000); console.log('網站伺服器啟動成功');
3. Express請求處理
3.1 構建模塊化路由
//路由對象也會有get、post方法 // 引入express框架 const express = require('express'); // 創建網站伺服器 const app = express(); // 創建路由對象 const home = express.Router(); // 為路由對象匹配請求路徑 app.use('/home', home); // 創建二級路由 home.get('/index', (req, res) => { res.send('歡迎來到博客首頁頁面') }) // 埠監聽 app.listen(3000);
把二級路由抽離出來模塊化,然後再app.js中引入
//home.js const express = require("express"); const home = express.Router(); home.get('/index', (req, res) => { res.send('歡迎來到博客首頁頁面') }); module.exports = home;
//admin.js const express = require("express"); const admin = express.Router(); admin.get('/index', (req, res) => { res.send('歡迎來到博客管理頁面') }); module.exports = admin;
// 引入express框架 const express = require('express'); // 創建網站伺服器 const app = express(); const home = require('./route/home'); const admin = require('./route/admin'); app.use('/home', home); app.use('/admin', admin); // 埠監聽 app.listen(3000);
3.2 GET參數的獲取
不再引用url模塊通過對請求地址進行解析來獲取請求參數,直接req.query即可獲取,框架內部會將GET參數轉換為對象並返回
// 引入express框架 const express = require('express'); // 創建網站伺服器 const app = express(); app.get('/index', (req, res) => { // 獲取get請求參數 res.send(req.query) }) // 埠監聽 app.listen(3000);
3.3 POST參數的獲取
Express中接收post請求參數需要藉助第三方包 body-parser。
//10.如何獲取post請求參數.js const express = require("express"); // 引入body-parser模塊 const bodyParser = require("body-parser"); const app = express(); //攔截所有請求 //extended:false 方法內部使用querystring模板處理請求參數的格式 //extended:true 方法內部使用第三方模塊qs處理請求參數的格式 // 配置body-parser模塊 app.use(bodyParser.urlencoded({ extended: false })); // 接收請求 app.post("/add", (req, res) => { //接受post請求參數 res.send(req.body); }); // 監聽埠 app.listen(3000);
<form action="http:localhost:3000/add" method='post'> <input type="text" name='username'> <input type="text" name='password'> <input type="submit" name=''> </form>
疑問:app.use方法需要傳遞一個請求處理函數進去,但是現在為什麼傳遞了一個方法的調用呢?
實際上調用的這個方法,它的返回值也是一個函數,這個返回的函數正好作為了app.use() 的參數。
這樣寫的好處就是調用fn函數的同時向fn函數內部傳遞一些額外的參數,在請求處理函數內部可以根據參數改變請求處理函數的行為
// 引入express框架 const express = require('express'); const bodyParser = require('body-parser'); // 創建網站伺服器 const app = express(); //攔截所有請求。把fn函數的調用寫在use的裡面,如果為1列印請求地址 app.use(fn ({a: 2})) function fn (obj) { return function (req, res, next) { if (obj.a == 1) { console.log(req.url) }else { console.log(req.method) } next() } } app.get('/', (req, res) => { // 接收post請求參數 res.send('ok') }) // 埠監聽 app.listen(3000);
3.4 Express路由參數
//傳遞和接受get參數還有另外一種方式,路由參數 //req.params獲取請求參數 // 引入express框架 const express = require('express'); const bodyParser = require('body-parser'); // 創建網站伺服器 const app = express(); app.get('/index/:id/:name/:age', (req, res) => { // 接收get請求參數 res.send(req.params) }) // 埠監聽 app.listen(3000);
3.5 靜態資源的處理
內置的express.static可以方便地托管靜態文件,例如img、CSS、JavaScript 文件等。
//通過express內置的express.static可以托管靜態文件,例如img/css/js文件等 //方法內部會判斷客戶端發來的請求是否是靜態資源請求,如果是直接響應給客戶端,終止當前請求 const express = require('express'); const path = require('path'); const app = express(); // 實現靜態資源訪問功能 //app.use(express.static(path.join(__dirname, 'public'))) //為靜態資源的目錄文件指定一個虛擬路徑 app.use('/static',express.static(path.join(__dirname, 'public'))) // 埠監聽 app.listen(3000);
4. express-art-template模板引擎
4.1 模板引擎
為了使art-template模板引擎能夠更好的和Express框架配合,模板引擎官方在原art-template模板引擎的基礎上封裝了express-art-template。
npm install art-template express-art-template
//14.模板引擎.js const express = require('express'); const path = require('path'); const app = express(); // 1.告訴express框架使用什麼模板引擎渲染什麼尾碼的模板文件 //app.engine('模板尾碼', require('使用的模板引擎')) app.engine('art', require('express-art-template')) // 2.設置模板存放目錄 //app.set('views為固定參數,express框架的配置項名字,告訴模板存放的位置',絕對路徑 views模板文件夾) app.set('views', path.join(__dirname, 'views')) // 3.渲染模板時不寫尾碼 預設拼接art尾碼 app.set('view engine', 'art'); app.get('/index', (req, res) => { //render功能: // 1. 拼接模板路徑 // 2. 拼接模板尾碼 // 3. '模板名稱',{key:value} // 4. 將拼接結果響應給了客戶端 res.render('index.art', { msg: 'message page' }) }); app.get('/list', (req, res) => { res.render('list', { msg: 'list page' }) }) // 埠監聽 app.listen(3000);
4.2 express模塊中的req,res參數的常用屬性方法
const express = require('express'); const router = express.Router() router.get('/',(req,res)=>{ // Request // req.baseUrl 基礎路由地址 // req.body post發送的數據解析出來的對象 // req.cookies 客戶端發送的cookies數據 // req.hostname 主機地址 去掉埠號 // req.ip 查看客戶端的ip地址 // req.ips 代理的IP地址 // req.originalUrl 對req.url的一個備份 // req.params 在使用/:id/:name 匹配params // req.path 包含請求URL的路徑部分 // req.protocol http 或https協議 // req.query 查詢字元串解析出來的對象 username=zhangsan&password=123 { username:zhangsan } // req.route 當前匹配的路由 正則表達式 // req.params 獲取路由匹配的參數 // req.get 獲取請求header里的參數 // req.is 判斷請求的是什麼類型的文件 // req.param(key名稱) 用來獲取某一個路由匹配的參數 //Response // res.headersSent 查看http響應是否響應了http頭 // res.append(名稱,value) 追加http響應頭 // res.attachment(文件路徑) 響應文件請求 // res.cookie() 設置cookie //res.setHeader('Content-Type','text/html;charset=utf8') // res.append('Content-Type','text/html;charset=utf8') // res.append('hehe','1008') // res.append('haha','1008') // res.attachment('./xx.zip') //Content-Disposition: attachment; filename="xx.zip" // res.clearCookie(cookiename) 刪除cookie // res.cookie('zhangsan','lisi') 設置cookie // res.cookie('zhangsan1','lisi2',{ // maxAge:900000, // httpOnly:true, // path: '/admin', // secure: true, // signed:true // }) // res.clearCookie('zhangsan') // res.download(文件的path路徑) 跟attachment類似 用來處理文件下載的 參數是文件地址 // res.end http模塊自帶的 // res.format()協商請求文件類型 format匹配協商的文件類型 // res.format({ // 'text/plain': function(){ // res.send('hey'); // }, // 'text/html': function(){ // res.send('<p>hey</p>'); // }, // 'application/json': function(){ // res.send({ message: 'hey' }); // }, // 'default': function() { // // log the request and respond with 406 // res.status(406).send('Not Acceptable'); // } // }); // res.get('key') 獲取響應header數據 // res.json() 返回json數據 會自動設置響應header Content-type 為json格式 application/json // res.json({ // xx:100 // }) // res.json({ // xx:100 // }) // jsonp 利用的就是瀏覽器載入其他伺服器的文件不會存在跨域問題 // ajax請求就會有跨域問題 // res.setHeader('Content-Type','text/javascript;charsert=utf8') // res.end(`typeof ${req.query.callback} == 'function' ? ${req.query.callback}({aa:100}):null`) // res.jsonp({aaa:100}) // 重定向 把訪問的地址跳轉到另一個地址上 // res.redirect(301,'/api/aes') // express jade // res.render('index',{title:"hehe",test:"23"}) // res.send('') 發送數據 可以是任意類型的數據 // res.sendFile() 發送文件的 // res.sendStatus(200) 設置發送時的狀態碼 // res.set('Content-Type', 'text/plain') //設置響應header // res.status(200) // 設置狀態碼 // res.type('') // 直接設置響應的文件類型 // res.type('pdf') // res.send({aa:100}) // res.end('ok') // res.end({aa:100}) // res.end('你好') // res.end(req.get('Accept-Language')) // res.json({ // is:req.is('text/html') // }) // res.json({ // type:req.baseUrl, // hostname:req.hostname, // // ip:req.ip, // // ips:req.ips, // // route:req.route, // ct:req.get('Accept'), // cs:'22' // }) }) router.get('/:id/:date',(req,res)=>{ console.log(req.params) // res.json(req.params) res.end(req.param('date')) }) router.get('/aes',(req,res)=>{ res.json({ type:req.baseUrl }) }) module.exports = router
參考:https://blog.csdn.net/weixin_40581714/article/details/111591005