1. 介紹
Express 是一個基于 Node.js 的 Web 應用程序框架,主要用于快速、簡便地構建 Web 應用程序 和 API。它是目前最流行的 Node.js Web 框架之一,具有輕量級、靈活和功能豐富的特點。
核心概念包括路由,中間件,請求與響應,以及模板引擎支持
2. Express應用的使用
通過npm進行安裝express包
npm install express
示例:以下是一個最簡單的Express應用程序
const express = require('express');
const app = express();// 路由:處理 GET 請求
app.get('/', (req, res) => {res.send('Hello, Express!');
});// 路由:處理動態參數
app.get('/user/:id', (req, res) => {res.send(`User ID: ${req.params.id}`);
});// 啟動服務器
const PORT = 3000;
app.listen(PORT, () => {console.log(`Server is running on http://localhost:${PORT}`);
});
3. 應用程序對象
Express的核心,負責注冊路由和中間件。
使用express()函數創建一個Express應用程序的實例。
const app = express();
4. 路由
Express提供了靈活的路由機制,用于定義應用如何響應客戶端的請求
get請求
用于從服務器獲取資源(例如網頁、數據),請求參數通常附加在URL的查詢字符串中,適用于獲取數據或無敏感信息的請求
const express = require('express');
const app = express();app.get('/', (req, res) => {res.send('歡迎訪問首頁!');
});// 帶查詢參數的 GET 請求
app.get('/search', (req, res) => {const query = req.query; // 獲取查詢參數res.send(`搜索內容:${query.keyword}`);
});app.listen(3000, () => console.log('服務器運行在 http://localhost:3000'));
訪問方式:直接在瀏覽器地址欄輸入即可
http://localhost:3000/search?keyword=express
request對象中包含了與HTTP請求相關的信息,例如請求頭,URL,參數等信息
屬性 | 描述 |
req.params | 包含動態路由中的參數,格式為對象。例如:/user/:id ,req.params.id 獲取 id 參數 |
req.query | 包含查詢字符串參數,格式為對象。例如:?name=John ,req.query.name 獲取 name 參數 |
req.body | 包含 POST 請求的請求體數據,需要中間件解析(如 express.json() 或 express.urlencoded() ) |
req.headers | 包含 HTTP 請求頭信息,格式為對象。 |
req.headers | 包含 HTTP 請求頭信息,格式為對象 |
req.method | HTTP 請求的方法,例如:GET 、POST 、PUT 、DELETE 等 |
req.url | 請求的完整 URL |
req.path | 請求的路徑部分(不包括查詢字符串) |
req.hostname | 請求的主機名,不包括端口號 |
req.ip | 客戶端的 IP 地址 |
示例:簡易的查找返回
const express = require("express")
const file = require("./test.json")
const app = express();app.get('/singer/:id.html',(req,res)=>{let {id} = req.params;let result = file.find(item=>{if (item.id === Number(id)){return true;}})if (!result){res.statusCode=404;renderBlock.end(`<h1>404 NOT FOUND<h1>`);return;}
})
post請求
post請求則是用于向服務器提交數據,例如表單數據,JSON數據,通常會改變服務器上的數據,例如添加,修改或刪除資源等操作
<!DOCTYPE html>
<html><head></head><body><form method="post" action="http://127.0.0.1:3000/submit"><textarea placeholder="輸入用戶名"></textarea><button>登錄</button></from></body>
</html>
const express = require('express');
const app = express();app.use(express.json()); // 解析 JSON 格式的請求體
app.use(express.urlencoded({ extended: true })); // 解析 URL 編碼的請求體// POST 路由
app.post('/submit', (req, res) => {const body = req.body; // 獲取請求體數據res.send(`提交的數據:${JSON.stringify(body)}`);
});app.listen(3000, () => console.log('服務器運行在 http://localhost:3000'));
response包含了與HTTP響應相關的方法和屬性,用于向客戶端返回數據
方法 | 描述 |
res.send(body) | 發送響應數據,可以是字符串,對象,Buffer等 |
res.json(body) | 發送 JSON 格式的響應 |
res.status(code) | 設置響應狀態碼,例如:res.status(404) |
res.redirect(url) | 重定向到指定 URL |
res.render(view, data) | 渲染視圖模板并發送響應(需要配置模板引擎) |
res.set(header, value) | 設置響應頭 |
res.cookie(name, value) | 設置 Cookie(需要 cookie-parser 中間件) |
res.clearCookie(name) | 清除指定的 Cookie |
res.type(type) | 設置content-type響應頭 |
res.sendFile() | 返回服務器中的文件 |
res.end() | 結束響應,但不發送數據 |
Response對象常見操作:
跳轉響應
app.get('/other',(req,res)=>{res.redirect('http://www.baidu.com')})
下載響應
app.get('/other',(req,res)=>{res.download(__dirname+'/package.json')})
JSON響應
app.get('/other',(req,res)=>{res.json({name:"Ricardo"})})
響應文件內容
用于展示HTML文件等信息
app.get('/other',(req,res)=>{res.sendFile(__dirname+'/test.html')})
4. express中間件
中間件(Middleware) 是 Express 中處理請求和響應的核心機制。它是一個函數,用于處理請求對象 (req
)、響應對象 (res
),以及在請求-響應周期中執行后續中間件的 next
方法,在路由處理之前或者之后執行。
簡單來講,中間件可以攔截請求、執行某些操作,然后決定是否將請求傳遞給下一個中間件;它們可以用來處理日志記錄、認證、數據解析、錯誤處理等任務。
中間件的基本形式:
function middleware(req, res, next) {// 中間件邏輯next(); // 調用 next() 將請求傳遞給下一個中間件
}
4.1?全局中間件
每一個請求到達服務器之后都會執行全局中間件函數,直接綁定到應用對象app上,作用域所有或指定的路由
const express = require("express");
const path = require("path");
const fs = require("fs");const app = express();// 聲明中間件函數
function recordMiddleware(req, res, next) {let { url, ip } = req;fs.appendFileSync(path.resolve(__dirname, './access.log'),`${url} ${ip}\r\n`);next(); // 必須調用 next() 將請求傳遞給后續中間件或路由
}// 使用中間件
app.use(recordMiddleware);app.get('/home', (req, res) => {res.send("Hello express");
});app.get('/admin', (req, res) => {res.send('后臺');
});// 處理 404 請求
app.all('*', (req, res) => {res.send("<h1>404 NOT FOUND</h1>");
});// 啟動服務器
app.listen(3000, () => {console.log("The server started on port 3000");
});
4.2 專有/路由級中間件
與路由綁定,僅作用于特定路由
function recordMiddleware(req, res, next) {let { url, ip } = req;fs.appendFileSync(path.resolve(__dirname, './access.log'),`${url} ${ip}\r\n`);next(); // 必須調用 next() 將請求傳遞給后續中間件或路由
}app.get('/home', recordMiddleware,(req, res) => {res.send("Hello express");
});
需要在中間件中聲明next才會進一步執行之后回調函數的內容
4.3 靜態資源/內置中間件
app.use(express.static(__dirname+'/public'));
根據在public文件夾下的路徑即可訪問對應的文件
如果public目錄下有index.html文件,單獨有index.html路由的話,根目錄代碼'/'書寫誰在前顯示誰
中間件 | 描述 | 安裝 |
express.json() | 解析 JSON 格式請求體 | 內置 |
express.urlencoded() | 解析 URL 編碼請求體(如表單數據) | 內置 |
express.static() | 提供靜態文件服務 | 內置 |
morgan | 記錄 HTTP 請求日志 | 需要安裝 |
cookie-parser | 解析請求中的 Cookie | 需要安裝 |
cors | 處理跨域請求 | 需要安裝 |
helmet | 提高應用安全性 | 需要安裝 |
body-parser | 解析請求體數據,功能與 express.json() 類似 | 需要安裝 |
express-session | 管理會話 | 需要安裝 |
示例:中間件獲取解析請求參數
首先,準備好我們的表單界面與服務端
<!DOCTYPE html>
<html><head></head><body><form action="http://127.0.0.1:3000/login" method="post">用戶名:<input type="text" name="username"><br>密碼:<input type="password" name="password"><br><button>登錄</button></form></body>
</html>
const express = require("express")const app = express();app.get('/login',(req,res)=>{res.sendFile(__dirname+'/form.html')
})app.post('/login',(req,res)=>{res.send('獲取用戶的數據')
})app.listen(3000,()=>{console.log('server is running...')
})
name=John&age=25
表單所返回的數據如上述所示,我們需要在服務器端獲取上述表單內容,需要使用到中間件?
使用中間件解析post請求所獲得的數據
const urlencodedParser = express.urlencoded({ extended: false });
使用中間件:
app.post('/login',urlencodedParser,(req,res)=>{console.log(req.body)res.send('獲取用戶的數據')
})
解析后的數據存放在req中body屬性中,解析的內容以對象的形式進行保存
{ name: 'John', age: '25' }
示例:防盜鏈
防止其他網站對資源進行訪問,通過header請求頭中refer所實現
app.use((req,res,next)=>{let referer = req.get('referer');if (referer){let url = new URL(referer);let hostname = url.hostname; //獲取站點信息if (hostname !== '127.0.0.1'){res.status(404).send('<h1>404 NOT FOUND</h1>')}
}
})
注意事項
1. 中間件順序很重要:中間件按照定義順序執行。
2. 確保調用next()如果不調用,后續中間件將不會執行。
5. 路由器(Router)
定義路由器級別的路由,用于為某一組路由邏輯進行模塊化管理(即創建“迷你應用”)。
它的作用范圍是局部的,綁定在特定的 Router
實例上。
反之使用app.get用于處理直接掛載到整個應用程序上的 HTTP GET 請求,作用范圍是全局的,綁定在整個 Express 應用實例上。
const express = require('express');
const app = express();
const router = express.Router();router.get('/about', (req, res) => res.send('關于頁面'));
router.get('/contact', (req, res) => res.send('聯系我們'));app.use('/info', router); // 將路由器掛載到 /info 路徑app.listen(3000);
最終訪問路由:
3000/info/about
6. 路由模塊化
單獨創建一個文件夾用于存儲不同作用的路由文件
// ./routes/網站首頁.js
const express = require('express')const router = express()router.get('/home',(req,res)=>{res.send("網站首頁")
})module.exports = router;
模塊化進行聲明導出,方便在主文件中進行使用
- 在主文件中配置路由,使用use掛載即可
// ./主文件.jsconst express = require("express");
const router = require('./route/home.js')const app = express();app.use(router);app.all("*",(req,res)=>{res.send("<h1>404 NOT FOUND<h1>")
})app.listen(3000,()=>{console.log("This server has been started")
})