Node.js Express框架全面解析
1、認(rèn)識(shí)express模塊
express模塊與http模塊很相似,都可以創(chuàng)建服務(wù)器。不同之處在于,express模塊將更多Web開發(fā)服務(wù)功能封裝起來,讓W(xué)eb應(yīng)用開發(fā)更加便捷。
什么是 Express?
Express 是 Node.js 平臺(tái)上最流行、最輕量級(jí)的 Web 應(yīng)用框架,被稱為 Node.js 的“事實(shí)標(biāo)準(zhǔn)”。它建立在 Node.js 內(nèi)置的 HTTP 模塊之上,提供了更簡潔、強(qiáng)大的 API 來構(gòu)建 Web 應(yīng)用和 RESTful API。
核心特點(diǎn)
- 極簡靈活:核心功能簡單,不強(qiáng)制約束項(xiàng)目結(jié)構(gòu)
- 中間件機(jī)制:強(qiáng)大的中間件體系,可輕松擴(kuò)展功能
- 路由系統(tǒng):直觀的路由定義方式
- 高性能:基于 Node.js 異步非阻塞特性
- 生態(tài)豐富:擁有大量第三方中間件
1.1、基本使用步驟
express模塊是第三方模塊,使用之前,首先需要使用npm命令進(jìn)行下載和安裝,命令如下:
npm install express@4
express模塊的版本變化非??欤厦姘惭b命令后面跟了“@4”?,表示安裝的是express 4.x版,如果不帶該后綴,則會(huì)自動(dòng)下載和安裝express模塊的最新版本。
express模塊安裝完后就可以在Node.js程序中使用了,其基本使用步驟如下。
- 導(dǎo)入模塊。
- 使用構(gòu)造函數(shù)創(chuàng)建Web服務(wù)器。
- 調(diào)用listen()方法啟動(dòng)Web服務(wù)器。
例如,下面代碼使用express模塊創(chuàng)建并啟動(dòng)了一個(gè)服務(wù)器,服務(wù)器地址為http://127.0.0.1:52273/,代碼如下:
//導(dǎo)入express模塊
const express = require('express');
//創(chuàng)建Web服務(wù)器
let app = express();
//啟動(dòng)Web服務(wù)器
app.listen(52273, ()=>{
console.log("服務(wù)器監(jiān)聽地址是 http://127.0.0.1:52273");
});
1.2、express中的響應(yīng)對(duì)象
express模塊提供了response對(duì)象,用來完成服務(wù)器端響應(yīng)操作,其常用方法及說明如表所示。
| 方法 | 說明 |
|---|---|
response.send([body]) | 根據(jù)參數(shù)類型,返回對(duì)應(yīng)數(shù)據(jù) |
response.json([body]) | 返回JSON數(shù)據(jù) |
response.redirect([status,]path) | 強(qiáng)制跳轉(zhuǎn)到指定頁面 |
根據(jù)body參數(shù)數(shù)據(jù)類型的不同,response對(duì)象可以向客戶端返回不同的數(shù)據(jù),如表所示。
| 數(shù)據(jù)類型 | 說明 |
|---|---|
| 字符串 | HTML格式的數(shù)據(jù) |
| 數(shù)組 | JSON格式的數(shù)據(jù) |
| 對(duì)象 | JSON格式的數(shù)據(jù) |
示例:實(shí)現(xiàn)向客戶端返回?cái)?shù)組信息。
新建一個(gè).js文件,首先導(dǎo)入express模塊,并通過其構(gòu)造函數(shù)創(chuàng)建一個(gè)Web服務(wù)器,然后使用use()方法創(chuàng)建一個(gè)數(shù)組,通過response對(duì)象的send()方法將其輸出到客戶端,最后使用listen()方法啟動(dòng)Web服務(wù)器。代碼如下:
//引入express模塊
const express = require('express');
//創(chuàng)建服務(wù)器
const app = express();
//監(jiān)聽請(qǐng)求與響應(yīng)
app.use((request, response)=>{
//創(chuàng)建數(shù)組
let output = [];
for (let i = 0; i < 3; i++) {
output.push({
count: i,
name: 'name - ' + i
});
}
//向客戶端返回?cái)?shù)組類型的信息
response.send(output);
});
//啟動(dòng)服務(wù)器
app.listen(52273, ()=>{
console.log('服務(wù)器監(jiān)聽地址在 http://127.0.0.1:52273');
});
運(yùn)行.js文件,在瀏覽器中輸入http://127.0.0.1:52273/,可以看到如圖14.1所示的界面效果。從圖14.1可以看出,向response對(duì)象的send()方法中傳遞了一個(gè)數(shù)組類型的參數(shù),返回給客戶端的是一個(gè)JSON數(shù)據(jù)。

1.3、express中的請(qǐng)求對(duì)象
express模塊提供了request對(duì)象,用來完成客戶端請(qǐng)求操作,其常用屬性、方法及說明如表所示。
| 屬性/方法 | 說明 |
|---|---|
params屬性 | 返回路由參數(shù) |
query屬性 | 返回請(qǐng)求變量 |
headers屬性 | 返回請(qǐng)求頭信息 |
header()方法 | 設(shè)置請(qǐng)求頭信息 |
accepts(type)方法 | 判斷請(qǐng)求accept屬性信息 |
is(type)方法 | 判斷請(qǐng)求Content-Type屬性信息 |
示例:判斷當(dāng)前請(qǐng)求用戶使用的瀏覽器類型。
新建一個(gè).js文件,導(dǎo)入express模塊,使用express()方法創(chuàng)建一個(gè)Web服務(wù)器,然后在use()方法中使用request.header(‘User-Agent’)方法獲取請(qǐng)求客戶端的User-Agent信息,通過判斷該信息確定用戶使用的瀏覽器類型。代碼如下:
//導(dǎo)入express模塊
const express = require('express');
//創(chuàng)建服務(wù)器
const app = express();
//監(jiān)聽請(qǐng)求和響應(yīng)
app.use((request, response)=>{
//獲取客戶端的User-Agent
let agent = request.header('User-Agent');
//判斷客戶端瀏覽器的類型
if (agent.toLowerCase().match(/chrome/)) {
//發(fā)送響應(yīng)信息
response.send('<h1>*_*歡迎使用谷歌瀏覽器</h1>');
} else {
//發(fā)送響應(yīng)信息
response.send('<h1>^_^您使用的不是谷歌瀏覽器,
當(dāng)然這并不影響瀏覽網(wǎng)頁</h1>');
}
});
//啟動(dòng)服務(wù)器
app.listen(52273, ()=>{
console.log('服務(wù)器監(jiān)聽地址在 http://127.0.0.1:52273');
});
2、express中間件
2.1、認(rèn)識(shí)中間件
app.use()方法在express模塊中的主要作用是注冊(cè)全局中間件。所謂中間件,是指業(yè)務(wù)流程的中間處理環(huán)節(jié)。app.use()方法的語法格式如下:
app.use([path,] callback[,callback])
path:可選參數(shù),指定的中間件函數(shù)的路徑(路由地址)?。callback:指定的中間件函數(shù),可以是多個(gè),并且這些回調(diào)函數(shù)可以調(diào)用next()。
使用app.use()方法將指定的中間件功能放到指定的路徑下,當(dāng)請(qǐng)求的路徑地址(客戶端發(fā)過來的地址)與定義的路由(app.get/post)相同時(shí),就會(huì)執(zhí)行指定的中間件功能。中間件的調(diào)用流程是:當(dāng)一個(gè)請(qǐng)求到達(dá)express的服務(wù)器后,可以連續(xù)調(diào)用多個(gè)中間件,從而對(duì)這次請(qǐng)求進(jìn)行預(yù)處理,在這中間,next()函數(shù)是實(shí)現(xiàn)多個(gè)中間件連續(xù)調(diào)用的關(guān)鍵,它表示把流轉(zhuǎn)關(guān)系轉(zhuǎn)交給下一個(gè)中間件或路由。
例如,新建一個(gè).js文件,使用express模塊創(chuàng)建一個(gè)Web服務(wù)器,然后使用兩次use()方法設(shè)置中間件,其中第一個(gè)use()方法中,定義了兩個(gè)變量,并通過next()設(shè)置了中間件,最后在第二個(gè)use()方法中使用第一個(gè)use()方法中定義的變量。代碼如下:
//導(dǎo)入express模塊
const express = require('express');
//創(chuàng)建服務(wù)器
let app = express();
//設(shè)置中間件
app.use((request, response, next)=>{
//定義變量
request.number = 20;
response.number =35;
next();
});
app.use((request, response, next)=>{
//發(fā)送響應(yīng)信息
response.send('<h1 style="color:green">' + request.number + ' : ' + response.number + '</h1>');
});
//啟動(dòng)服務(wù)器
app.listen(52273, ()=>{
console.log('服務(wù)器監(jiān)聽地址在 http://127.0.0.1:52273');
});

express中常用的中間件及說明如表所示。
| 中間件 | 說明 |
|---|---|
router | 處理頁面間的路由 |
static | 托管靜態(tài)文件,如圖片、CSS文件和JavaScript文件等 |
morgan | 日志組件 |
cookie parser | cookie驗(yàn)證簽名組件 |
body parser | 對(duì)post請(qǐng)求進(jìn)行解析 |
connect-multiparty | 文件上傳中間件 |
2.2、router中間件
express模塊中使用router中間件來處理頁面路由。在http模塊中,通常使用if語句來處理頁面的路由跳轉(zhuǎn),而在express模塊中,使用router中間件就可以很方便地實(shí)現(xiàn)頁面的路由跳轉(zhuǎn)。router中間件的常用方法及說明如表所示。
| 方法 | 說明 |
|---|---|
get(path,callback[,callback]) | 處理GET請(qǐng)求 |
post(path,callback[,callback]) | 處理POST請(qǐng)求 |
pull(path,callback[,callback)] | 處理PULL請(qǐng)求 |
delete(path,callback[,callback]) | 處理DELETE請(qǐng)求 |
all(path,callback[,callback]) | 處理所有請(qǐng)求 |
例如,新建一個(gè).js文件,使用express模塊創(chuàng)建一個(gè)Web服務(wù)器,然后使用app.get()方法設(shè)置頁面的路由跳轉(zhuǎn)規(guī)則,在訪問頁面時(shí)需要使用“/page/id”的形式。代碼如下:
//導(dǎo)入express模塊
const express = require('express');
//創(chuàng)建服務(wù)器
let app = express();
//設(shè)置頁面路由規(guī)則
app.get('/page/:id', (request, response)=>{
//獲取request對(duì)象
let name = request.params.id;
//發(fā)送響應(yīng)信息
response.send('<h2 style="color:red">' + name + ' Page</h2>');
});
//啟動(dòng)服務(wù)器
app.listen(52273, ()=>{
console.log('服務(wù)器監(jiān)聽地址在 http://127.0.0.1:52273');
});

2.3、static中間件
static中間件是express模塊內(nèi)置的托管靜態(tài)文件的中間件,可以非常方便地將圖片、視頻、CSS文件和JavaScript文件等資源導(dǎo)入項(xiàng)目中。static中間件的使用方法如下:
express.static(root[,options])
root:指定從中提供靜態(tài)資源的根目錄。options:可選參數(shù),指定一些配置選項(xiàng)。
示例:實(shí)現(xiàn)向客戶端返回圖片。
本實(shí)例需要在項(xiàng)目中創(chuàng)建一個(gè)文件夾,名稱為image,在該文件夾中存放一張圖片,名為view.jpg;然后創(chuàng)建一個(gè).js文件,在該文件中,首先使用express模塊創(chuàng)建Web服務(wù)器,然后使用express.static()方法設(shè)置靜態(tài)中間件,以便導(dǎo)入圖片資源,其中__dirname表示項(xiàng)目的根目錄。代碼如下:
const express = require('express');
//創(chuàng)建服務(wù)器
let app = express();
//使用static中間件
app.use(express.static(__dirname + '/image'));
app.use((request, response)=>{
//發(fā)送響應(yīng)信息
response.writeHead(200, {'Content-Type': 'text/html'});
response.end('<img src="/82.jpg" width="100%" />');
});
//啟動(dòng)服務(wù)器
app.listen(52273, ()=>{
console.log('服務(wù)器地址在 http://127.0.0.1:52273');
});

2.4、cookie parser中間件
cookie parser中間件主要用來處理cookie請(qǐng)求與響應(yīng),由于cookie parser中間件不是express模塊內(nèi)置的中間件,因此需要通過npm命令進(jìn)行下載和安裝,命令如下:
npm install cookie-parser
cookie parser中間件的使用方法如下:
cookie parser([secret])
- 參數(shù)secret為可選參數(shù),用來設(shè)置加密簽名。
例如,創(chuàng)建一個(gè).js文件,通過在app.use()方法中調(diào)用cookieParser()來設(shè)置一個(gè)沒有簽名的cookie parser中間件,然后設(shè)置服務(wù)器端響應(yīng)的cookie內(nèi)容,并將該響應(yīng)信息發(fā)送到客戶端進(jìn)行顯示。代碼如下:
//導(dǎo)入模塊
const express = require('express');
const cookieParser = require('cookie-parser');
//創(chuàng)建服務(wù)器
let app = express();
//設(shè)置cookie parser中間件
app.use(cookieParser());
app.get('/', (request, response)=>{
//設(shè)置cookie內(nèi)容
response.cookie('string', 'cookie');
response.cookie('json', {
name: 'cookie',
property: 'delicious'
})
response.send(request.cookies)
app.get('/get', (request, response)=>{
//發(fā)送響應(yīng)信息
response.send(request.cookies);
});
});
//啟動(dòng)服務(wù)器
app.listen(52273, ()=>{
console.log('服務(wù)器地址在 http://127.0.0.1:52273');
});

2.5、body parser中間件
body parser中間件主要用來處理POST請(qǐng)求數(shù)據(jù),使用body parser中間件的前提是設(shè)置request對(duì)象的body屬性。body parser中間件不是express對(duì)象內(nèi)置的中間件,需要使用npm命令進(jìn)行下載和安裝,命令如下:
npm install body-parser
body parser中間件的常用方法及說明如表所示。
| 方法 | 說明 |
|---|---|
bodyParser.json([options]) | 返回只解析JSON的中間件 |
bodyParser.raw([options]) | 將請(qǐng)求體內(nèi)容作為Buffer或者字符串來處理并返回 |
bodyParser.urlencoded([options]) | 中間件只解析并返回urlencoded請(qǐng)求體,只支持UTF-8編碼 |
示例:通過設(shè)置中間件實(shí)現(xiàn)登錄驗(yàn)證功能。
- 在WebStorm中創(chuàng)建js.js文件,在該文件中,主要通過cookie parser中間件和body parser中間件結(jié)合,實(shí)現(xiàn)用戶登錄驗(yàn)證的功能。其中,cookie parser中間件用來記錄用戶登錄成功標(biāo)識(shí),body parser中間件用來處理用戶登錄請(qǐng)求數(shù)據(jù)。另外,通過app.get()方法分別設(shè)置了初始頁面、登錄成功頁面和登錄失敗頁面的路由規(guī)則。代碼如下:
const fs = require('fs');
const express = require('express');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
//創(chuàng)建服務(wù)器
let app = express();
//設(shè)置中間件
app.use(cookieParser());
//extended選項(xiàng)為false,表示使用querystring庫轉(zhuǎn)換URL-encoded數(shù)據(jù)
app.use(bodyParser.urlencoded({ extended: false }));
//設(shè)置路由配置
app.get('/', (request, response)=>{
if (request.cookies.auth) {
response.send('<h1 style="color:red;text-align: center">登錄成功</h1>');
} else {
response.redirect('/login');
}
});
app.get('/login', (request, response)=>{
//讀取登錄頁面
fs.readFile('login.html', (error, data)=>{
response.send(data.toString());
});
});
app.post('/login', (request, response)=>{
//記錄登錄用戶
let login = request.body.login;
//記錄登錄密碼
let pass = request.body.pass;
//判斷登錄是否成功
if (login == 'mingrisoft' && pass == '123456') {
//登錄成功,使用cookie記錄登錄成功標(biāo)識(shí)
response.cookie('auth', true);
response.redirect('/'); //跳轉(zhuǎn)頁面
} else {
//登錄失敗
response.redirect('/login');
}
});
//啟動(dòng)服務(wù)器
app.listen(52273, ()=>{
console.log('服務(wù)器監(jiān)聽地址是 http://127.0.0.1:52273');
});- 創(chuàng)建login.html文件,用來作為用戶登錄頁面,代碼如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>登錄頁面</title>
</head>
<body>
<form method="post">
<fieldset style="width: 250px;margin: 0 auto;padding:20px">
<legend style="color:#ff5722">管理員登錄</legend>
<table>
<tr>
<td>
<label for="user">賬 號(hào):</label>
</td>
<td>
<input type="text" name="login" id="user"/>
</td>
</tr>
<tr height="40">
<td>
<label for="pass">密 碼:</label>
</td>
<td>
<input type="pass" name="pass" id="pass"/>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" style="background: #41d7ea;width: 85px;height: 25px;
border: 1px solid #e0ac5e;outline: none;border-radius: 5px;"/>
</td>
</tr>
</table>
</fieldset>
</form>
</body>
</html>運(yùn)行js.js文件,在瀏覽器中輸入http://127.0.0.1:52273/,可以看到一個(gè)管理員登錄頁面,如圖所示。

在頁面中輸入賬號(hào)(mingrisoft)和密碼(123456),單擊“提交”按鈕,效果如圖所示。

3、實(shí)現(xiàn)RESTful Web服務(wù)
RESTful Web服務(wù)是基于REST架構(gòu)的Web服務(wù),它是輕量級(jí)的,具有高度的可擴(kuò)展性和可維護(hù)性,Web應(yīng)用非常適合于按照RESTful服務(wù)的統(tǒng)一標(biāo)準(zhǔn)進(jìn)行開發(fā),下表是通用的表示用戶信息的RESTful Web服務(wù)標(biāo)準(zhǔn)。
| 路由 | 說明 |
|---|---|
GET /user | 查詢所有的用戶信息 |
GET /user/273 | 查詢id為273的用戶信息 |
POST /user | 添加用戶信息 |
PUT /user/273 | 修改id為273的用戶信息 |
DELETE /user/273 | 刪除id為273的用戶信息 |
示例:實(shí)現(xiàn)用戶信息的RESTful服務(wù)。
- 創(chuàng)建虛擬數(shù)據(jù)庫。本實(shí)例的用戶信息存儲(chǔ)在一個(gè)虛擬數(shù)據(jù)庫中,該數(shù)據(jù)庫使用JSON對(duì)象來表示,該對(duì)象中主要通過對(duì)數(shù)組的操作實(shí)現(xiàn)數(shù)據(jù)的查詢、添加和刪除功能,代碼如下:
//創(chuàng)建虛擬數(shù)據(jù)庫
module.exports = (function(){
let DummyDB = {};
let storage = [];
let count = 1;
//查詢數(shù)據(jù)庫
DummyDB.get = (id)=>{
if(id) {
//將id轉(zhuǎn)換為數(shù)字類型
id = (typeof id == 'string') ? Number(id) : id;
//遍歷存儲(chǔ)數(shù)據(jù),并判斷是否找到相應(yīng)的id
for(let i in storage) {
if(storage[i].id == id){
return storage[i];
}
}
} else {
return storage;
}
}
//添加數(shù)據(jù)
DummyDB.insert = (data)=>{
data.id = count++;
storage.push(data);
return data;
}
//刪除數(shù)據(jù)
DummyDB.remove = (id)=>{
id = (typeof id == 'string') ? Number(id) : id;
for(let i in storage) {
if(storage[i].id == id) {
//刪除數(shù)據(jù)
storage.splice(i, 1);
return true;
}
}
return false;
}
return DummyDB;
})();- 使用POST請(qǐng)求添加數(shù)據(jù)。實(shí)現(xiàn)通過POST請(qǐng)求添加數(shù)據(jù)的功能時(shí),首先需要一個(gè)添加頁面,本實(shí)例中使用一個(gè)用戶登錄頁面addUser.html來表示該頁面,當(dāng)用戶在頁面中輸入用戶名和密碼并單擊“提交”按鈕后,會(huì)自動(dòng)將用戶輸入的信息保存到虛擬數(shù)據(jù)庫中。addUser.html頁面的代碼如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>add User</title>
</head>
<body>
<form method="post">
<fieldset style="width: 250px;margin: 0 auto;padding:20px">
<legend style="color:#ff5722">登錄賬戶</legend>
<table>
<tr>
<td><label>用戶名:</label></td>
<td><input type="text" name="name"/></td>
</tr>
<tr height="40">
<td><label>密 碼:</label></td>
<td><input type="password" name="pass"/></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" style="background: #41d7ea;width: 85px;height: 25px;
border: 1px solid #e0ac5e;outline: none;border-radius: 5px;"/>
</td>
</tr>
</table>
</fieldset>
</form>
</body>
</html>- 接口:
const fs = require('fs');
const express = require('express');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const DummyDB = require('./db.js');
//創(chuàng)建服務(wù)器
let app = express();
//設(shè)置中間件
app.use(cookieParser());
//extended選項(xiàng)為false,表示使用querystring庫轉(zhuǎn)換URL-encoded數(shù)據(jù)
app.use(bodyParser.urlencoded({ extended: false }));
//查詢所有用戶信息
app.get('/user', (request, response)=>{
response.send(DummyDB.get());
});
//查詢指定id的用戶信息
app.get('/user/:id', (request, response)=>{
response.send(DummyDB.get(request.params.id));
});
//添加用戶
app.get('/addUser', (request, response)=>{
fs.readFile('addUser.html', (error, data)=>{
response.send(data.toString());
});
});
app.post('/addUser', (request, response)=>{
let name = request.body.name;
let pass = request.body.pass;
if(name && pass) {
response.send(DummyDB.insert({
name: name,
pass: pass
}));
} else {
throw new Error('error');
}
});
//刪除指定id的用戶
app.delete('/user/:id', (request, response)=>{
if(DummyDB.remove(request.params.id)) {
response.send('刪除成功');
}else{
response.send('刪除失敗');
}
})
//啟動(dòng)服務(wù)器
app.listen(52273, ()=>{
console.log('服務(wù)器監(jiān)聽地址是 http://127.0.0.1:52273');
});添加用戶:


查詢所有:

根據(jù)id查詢:
根據(jù)id刪除:
4、express-generator模塊
前面介紹了express模塊的基本應(yīng)用,在使用express模塊編寫程序時(shí),都是手動(dòng)編寫代碼,這在實(shí)際開發(fā)中比較耗時(shí)且效率低,這時(shí)可以使用express-generator模塊。express-generator模塊是express的應(yīng)用生成器,通過該模塊,可以快速創(chuàng)建一個(gè)express應(yīng)用。
4.1、創(chuàng)建項(xiàng)目
express-generator模塊與express模塊一樣,也是第三方模塊,因此在使用之前,需要進(jìn)行安裝,命令如下:
npm install -g express-generator
安裝完成以后,就可以使用express-generator來創(chuàng)建項(xiàng)目了。步驟如下。
- 創(chuàng)建項(xiàng)目。創(chuàng)建項(xiàng)目時(shí),首先需要使用“cd項(xiàng)目路徑”命令來切換并選擇路徑,然后使用“express項(xiàng)目名稱”命令來創(chuàng)建項(xiàng)目。例如,圖14.11所示為通過WebStorm的命令終端在指定路徑下創(chuàng)建了一個(gè)名稱為my_project的項(xiàng)目。項(xiàng)目創(chuàng)建完成后,控制臺(tái)會(huì)顯示項(xiàng)目的相關(guān)命令,如安裝項(xiàng)目所需模塊、啟動(dòng)項(xiàng)目等命令。
cd ../ express my_project
- 打開創(chuàng)建的項(xiàng)目文件夾,可看到自動(dòng)生成了多個(gè)文件和文件夾,它們的作用如圖所示。

使用express-generator模塊創(chuàng)建的項(xiàng)目,默認(rèn)使用jade模板引擎,即第pug模板,jade文件的結(jié)構(gòu)及語法與pug文件一致。
- 繼續(xù)在命令終端中輸入命令,可以進(jìn)入項(xiàng)目,并安裝相關(guān)模塊,具體如圖所示。

- 所有配置完成后,使用命令“npm start”啟動(dòng)該項(xiàng)目,如圖14.14所示,打開瀏覽器,輸入網(wǎng)址http://127.0.0.1:3000(初始端口號(hào)為3000)?,可以看到瀏覽器運(yùn)行效果如圖所示。

4.2、設(shè)置項(xiàng)目參數(shù)
在創(chuàng)建項(xiàng)目時(shí),還可以同時(shí)設(shè)定項(xiàng)目的參數(shù),如模板類型等。在終端對(duì)話框中使用“express–help”命令,可以查看使用express-generator模塊創(chuàng)建項(xiàng)目時(shí)能夠設(shè)置的參數(shù),如圖所示。各參數(shù)說明如表所示。

express-generator模塊可以設(shè)置的參數(shù):
| 參數(shù) | 說明 |
|---|---|
h或者-help | 輸出幫助信息 |
--version | 輸出Exp框架的版本信息 |
-e或者-ejs | 使用ejs模板類型 |
--hbs | 使用handlebars引擎 |
-H或者一hogan | 使用hogan.js |
-v<engine>或者-view<engine> | 添加視圖引擎支持,默認(rèn)為jade,可選值有dust、ejs、hbs、hjs、jade、pug、twig、vash |
-c<engine>或者-css<engine> | 使用樣式 |
--git | 自動(dòng)生成.gitignore文件 |
-f或者-force | 強(qiáng)制創(chuàng)建項(xiàng)目 |
例如,創(chuàng)建一個(gè)名稱為project的項(xiàng)目,并且設(shè)置要使用的模板引擎為ejs,則創(chuàng)建項(xiàng)目的命令如下:
express –e project
4.3、 express-generator模塊應(yīng)用
實(shí)現(xiàn)網(wǎng)站的登錄和退出功能。
要實(shí)現(xiàn)該項(xiàng)目,首先使用express-generator創(chuàng)建項(xiàng)目,項(xiàng)目名稱為login,命令如下:
express login
進(jìn)入項(xiàng)目并下載項(xiàng)目的相關(guān)模塊,命令如下。
cd login npm install
準(zhǔn)備工作完成后,接下來完成項(xiàng)目的實(shí)際功能,步驟如下。
- 配置app.js文件。打開app.js文件,在該文件中,將項(xiàng)目的模板引擎修改為ejs,并將ejs模板映射至html文件,這樣就可以直接在項(xiàng)目中訪問html文件;然后通過中間件對(duì)網(wǎng)站的session信息進(jìn)行設(shè)置;最后分別使用app.get()方法和app.set()方法實(shí)現(xiàn)設(shè)置用戶登錄狀態(tài)、用戶登錄及用戶退出的接口。代碼如下:
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var session = require('express-session');
var FileStore = require('session-file-store')(session);
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
//導(dǎo)入自定義模塊
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
//創(chuàng)建服務(wù)器對(duì)象
var app = express();
var identityKey = 'skey';
var users = require('./routes/user').items;
var findUser = function(name, password){
return users.find((item)=>{
return item.name === name && item.password === password;
})
}
//對(duì)服務(wù)器進(jìn)行設(shè)置
app.set('views', path.join(__dirname, 'views'));
var ejs = require('ejs');
//將ejs模板映射至html文件
app.engine(".html", ejs.__express);
app.set("view engine", "html");
//設(shè)置中間件
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({
name: identityKey,
secret: 'mingrisoft', //用來對(duì)session_id相關(guān)的cookie進(jìn)行簽名
store: new FileStore(), //本地存儲(chǔ)session
saveUninitialized: false, //是否自動(dòng)保存未初始化的會(huì)話
resave: false, //是否每次都重新保存會(huì)話
cookie: {
maxAge: 1000 * 1000 //有效期,單位是毫秒
}
}));
//GET請(qǐng)求,設(shè)置用戶登錄狀態(tài)
app.get("/", function(req, res, next){
var sess = req.session;
var loginUser = sess.loginUser;//記錄登錄用戶
var isLogined = !loginUser; //將登錄用戶變量轉(zhuǎn)換為對(duì)應(yīng)的布爾值
res.render("index", {
isLogined: isLogined,
name: loginUser
});
});
//Post請(qǐng)求,判斷用戶是否能夠登錄成功
app.post("/login", function(req, res, next){
var sess = req.session;
var user = findUser(req.body.name, req.body.password);
if(user) {
req.session.regenerate(function(err){
if(err){
return res.json({ret_code: 2, ret_msg: '登錄失敗'});
}
req.session.loginUser = user.name;
res.json({ret_code: 0, ret_msg: '登錄成功'});
})
} else {
res.json({ret_code: 1, ret_msg: '賬號(hào)或密碼錯(cuò)誤'});
}
});
//GET請(qǐng)求,退出登錄時(shí),清空session
app.get("/logout", function(req, res, next){
req.session.destroy(function(err){
if(err){
res.json({ret_code:2, ret_msg: '退出登錄s失敗'});
return;
}
res.clearCookie(identityKey);
res.redirect("/");
});
});
app.use('/', indexRouter);
app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
設(shè)置網(wǎng)站的session信息時(shí),使用了express-session和session-fill-store模塊。其中,express-session模塊用來將會(huì)話數(shù)據(jù)存儲(chǔ)在服務(wù)器上,默認(rèn)為內(nèi)存存儲(chǔ),所以一旦express服務(wù)器被重啟,那么session數(shù)據(jù)將會(huì)丟失,而session-fill-store模塊解決了這個(gè)問題,它提供了本地文件的存儲(chǔ),這樣,即使服務(wù)器重啟后,如果用戶訪問頁面,訪問的狀態(tài)還在。因此,express-session和session-fill-store模塊通常都一起配合使用。
- 定義用戶信息。新建一個(gè)user.js文件,作為虛擬數(shù)據(jù)庫,在該文件中,添加用戶名和密碼,當(dāng)用戶輸入的用戶名和密碼與該文件中的用戶名和密碼匹配時(shí),客戶端頁面中顯示當(dāng)前登錄用戶。user.js文件中的代碼如下:
module.exports = {
items: [
{name: 'mingrisoft', password: '123456'}
]
};
- 修改客戶端頁面。由于在app.js文件中,頁面的模板引擎修改為ejs,并且直接映射至html文件,因此需要將views文件夾中默認(rèn)的jade文件的后綴修改為html。打開修改后的index.html文件,在該文件中首先添加用戶登錄相關(guān)的表單元素;然后判斷用戶登錄狀態(tài),以確定要顯示的HTML標(biāo)簽元素;最后為“登錄”按鈕添加單擊事件,記錄用戶輸入的用戶名和密碼,并定義一個(gè)函數(shù),判斷如果是登錄成功狀態(tài),則刷新頁面。index.html文件中的代碼如下:
<!DOCTYPE html>
<html>
<head>
<title>會(huì)話管理</title>
</head>
<body>
<h2 style="text-align: center">會(huì)話管理</h2>
<p id="loged">
當(dāng)前登錄用戶:<span style="color:red"><%= name %></span>,<a href="/logout" rel="external nofollow" id="logout">退出登錄</a>
</p>
<fieldset style="width: 300px;text-align: center;margin: 10px auto;border:1px solid #4caf50" id="unlog">
<legend style="text-align: left">登錄</legend>
<form method="POST" action="/login">
<label style="display: block;margin-top: 20px">
用戶名:<input type="text" id="name" name="name" value=""/>
</label>
<label style="display: block;margin: 20px auto">
密 碼:<input type="password" id="password" name="password" value=""/>
</label>
<div style="text-align: center;margin-bottom: 10px">
<input type="submit" value="登錄" id="login" style="background: #cddc39;border:1px solid #ff9800"/>
</div>
</form>
</fieldset>
<script type="text/javascript" src="/jquery-3.1.0.min.js"></script>
<script>
if (isLogined) {
$("#loged").css("display", "block")
$("#unlog").css("display", "none")
}
else {
$("#unlog").css("display", "block")
$("#loged").css("display", "none")
}
</script>
<script type="text/javascript">
$('#login').click(function (evt) {
evt.preventDefault();
$.ajax({
url: '/login',
type: 'POST',
data: {
name: $('#name').val(),
password: $('#password').val()
},
success: function (data) {
if (data.ret_code === 0) {
location.reload();
}
}
});
});
</script>
</body>
</html>
- 打開修改后的error.html文件,在該頁面中設(shè)置錯(cuò)誤信息,代碼如下:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>出錯(cuò)了</title>
</head>
<body>
<script>
document.getElementById("mess").innerHTML=message;
document.getElementById("err").innerHTML=error;
document.getElementById("errt").innerHTML=error.stack;
</script>
</body>
</html>
- 更改端口號(hào)。默認(rèn)情況下,項(xiàng)目的端口號(hào)為3000,用戶可以根據(jù)自己的需要更改為其他端口號(hào),更改端口號(hào)需要在項(xiàng)目的bin\www文件中進(jìn)行,比如,這里將端口號(hào)修改為52273,代碼如下:
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '52273');
app.set('port', port);
- 運(yùn)行項(xiàng)目。首先在WebStorm終端命令對(duì)話框或者系統(tǒng)的“命令提示符”對(duì)話框中啟動(dòng)項(xiàng)目,啟動(dòng)項(xiàng)目時(shí),可以使用命令“npm start”?,也可以進(jìn)入項(xiàng)目的bin文件夾中,使用命令“node www”?,然后打開瀏覽器,輸入網(wǎng)址http:\127.0.0.1:52273,初始效果如圖所示。

輸入用戶名與密碼,單擊“登錄”按鈕,運(yùn)行效果如圖所示:


5、Koa框架
5.1、認(rèn)識(shí)Koa框架
Koa框架是基于Node.js平臺(tái)的一個(gè)新的Web開發(fā)框架,由Express幕后的原班人馬打造,致力于成為Web應(yīng)用和API開發(fā)領(lǐng)域中的更小、更富有表現(xiàn)力、更健壯的基石。通過利用async函數(shù),Koa框架中丟棄了回調(diào)函數(shù),并增強(qiáng)了錯(cuò)誤處理,它沒有捆綁任何中間件,而是提供了一套優(yōu)雅的方法,幫助開發(fā)者快速而愉快地編寫服務(wù)端應(yīng)用程序。
要使用Koa框架,首先需要進(jìn)行安裝,命令如下:
npm install koa
5.2、Koa框架的基本使用
使用Koa框架時(shí),首先需要進(jìn)行導(dǎo)入,并創(chuàng)建其對(duì)象,然后調(diào)用其屬性或方法實(shí)現(xiàn)相應(yīng)的功能,導(dǎo)入Koa框架的代碼如下:
const Koa = require('koa');
const app = new Koa();
Koa對(duì)象提供的主要屬性、方法及說明如表所示。
| 屬性/方法 | 說明 |
|---|---|
app.keys屬性 | 設(shè)置簽名的cookie密鑰 |
app.context屬性 | Koa框架中Context上下文對(duì)象ctx的原型,可以通過編輯該屬性為ctx添加其他屬性 |
app.listen()方法 | 創(chuàng)建并返回HTTP服務(wù)器,將給定的參數(shù)傳遞給服務(wù)器端listen() |
app.callback() | 方法返回適用于http.createServer()方法的回調(diào)函數(shù)來處理請(qǐng)求,也可以使用此回調(diào)函數(shù)將Koa應(yīng)用程序掛載到Connect//Express應(yīng)用程序中 |
app.use(function)方法 | 將給定的中間件方法添加到此應(yīng)用程序 |
ctx表示Koa Context上下文,它將Node.js的request和response對(duì)象封裝到單個(gè)對(duì)象中,它為編寫Web應(yīng)用程序和API提供了許多有用的方法,這些方法會(huì)在HTTP服務(wù)器開發(fā)中頻繁使用,每個(gè)請(qǐng)求都將創(chuàng)建一個(gè)Context,并在中間件中作為接收器引用。Context的常用方法和屬性如表所示。
| 屬性/方法 | 說明 |
|---|---|
ctx.req | Node.js的request對(duì)象 |
ctx.res | Node.js的response對(duì)象 |
ctx.request | Koa的Request對(duì)象 |
ctx.responses | Koa的Response對(duì)象 |
ctx.state | 推薦的命名空間,用于通過中間件傳遞信息和前端視圖 |
ctx.app | 應(yīng)用程序?qū)嵗?/td> |
ctx.app.emit | 發(fā)出一個(gè)類型由第一個(gè)參數(shù)定義的事件 |
ctx.cookies.get(name[,options]) | 通過options獲取cookie name |
ctx.cookies.set(name,value[,options]) | 通過options設(shè)置cookie name的value |
ctx.throw([status][,msg][,properties]) | 拋出一個(gè)包含.status屬性錯(cuò)誤的幫助方法,其默認(rèn)值為500 |
ctx.assert(value[,status][,msg][,properties]) | 當(dāng)!value時(shí)拋出一個(gè)類似.throw錯(cuò)誤的幫助方法 |
例如,使用Koa框架創(chuàng)建一個(gè)服務(wù)器,并設(shè)置輸出內(nèi)容為經(jīng)典的“Hello World”?,代碼如下:
const Koa = require('koa');
const app = new Koa();
app.use(async ctx => {
ctx.body = 'Hello World';
});
app.listen(3000);

Koa框架中同樣支持next中間件,例如,下面使用Koa創(chuàng)建一個(gè)服務(wù)器,然后分別在兩個(gè)use訪問器中設(shè)置輸出內(nèi)容,并且使用next中間件設(shè)置內(nèi)容的輸出順序,代碼如下:
const Koa = require("koa")
const app = new Koa()
app.use((ctx, next) => {
console.log("first")
next() //設(shè)置中間件
console.log("third")
ctx.body = '在koa中使用中間件';
})
app.use((ctx, next) => {
//同步操作
console.log("second")
})
app.listen(3000)

到此這篇關(guān)于Node.js Express框架全面解析的文章就介紹到這了,更多相關(guān)node.js express框架內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Node.js express的基本使用詳解
- Node.js 使用 Express-Jwt和JsonWebToken 進(jìn)行Token身份驗(yàn)證的操作方法
- node.js express cors解決跨域的示例代碼
- 使用?Node.js和Express搭建服務(wù)器的過程步驟詳解
- Node.js中Express框架使用axios同步請(qǐng)求(async+await)實(shí)現(xiàn)方法
- node.js使用express-jwt報(bào)錯(cuò):expressJWT?is?not?a?function解決
- Node.js使用express寫接口的具體代碼
- Node.js?express中的身份認(rèn)證的實(shí)現(xiàn)
相關(guān)文章
Vue+Node服務(wù)器查詢Mongo數(shù)據(jù)庫及頁面數(shù)據(jù)傳遞操作實(shí)例分析
這篇文章主要介紹了Vue+Node服務(wù)器查詢Mongo數(shù)據(jù)庫及頁面數(shù)據(jù)傳遞操作,結(jié)合實(shí)例形式分析了node.js查詢MongoDB數(shù)據(jù)庫及vue前臺(tái)頁面渲染等相關(guān)操作技巧,需要的朋友可以參考下2019-12-12
node.js調(diào)用Chrome瀏覽器打開鏈接地址的方法
其實(shí)在Node.JS中打開瀏覽器網(wǎng)址非常簡單,但還是有必要整理下分享給有需要的朋友們,這篇文章主要給大家介紹了node.js如何調(diào)用Chrome瀏覽器打開鏈接地址的方法,文中介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起看看吧。2017-05-05
nodejs實(shí)現(xiàn)獲取本地文件夾下圖片信息功能示例
這篇文章主要介紹了nodejs實(shí)現(xiàn)獲取本地文件夾下圖片信息功能,涉及node.js針對(duì)文件、目錄的遍歷、讀取等相關(guān)操作技巧,需要的朋友可以參考下2019-06-06

