Express 簡介
Express 是一個(gè)簡潔而靈活的 node.js Web應(yīng)用框架, 提供了一系列強(qiáng)大特性幫助你創(chuàng)建各種 Web 應(yīng)用,和豐富的 HTTP 工具饶号。
使用 Express 可以快速地搭建一個(gè)完整功能的網(wǎng)站激率。
Express 框架核心特性:
可以設(shè)置中間件來響應(yīng) HTTP 請(qǐng)求咳燕。
定義了路由表用于執(zhí)行不同的 HTTP 請(qǐng)求動(dòng)作。
可以通過向模板傳遞參數(shù)來動(dòng)態(tài)渲染 HTML 頁面柱搜。
01迟郎、安裝 Express
安裝 Express 并將其保存到依賴列表中:
$ cnpm install express --save
以上命令會(huì)將 Express 框架安裝在當(dāng)前目錄的 node_modules 目錄中, node_modules 目錄下會(huì)自動(dòng)創(chuàng)建 express 目錄聪蘸。以下幾個(gè)重要的模塊是需要與 express 框架一起安裝的:
body-parser - node.js 中間件宪肖,用于處理 JSON, Raw, Text 和 URL 編碼的數(shù)據(jù)。
cookie-parser - 這就是一個(gè)解析Cookie的工具健爬。通過req.cookies可以取到傳過來的cookie控乾,并把它們轉(zhuǎn)成對(duì)象。
multer - node.js 中間件娜遵,用于處理 enctype="multipart/form-data"(設(shè)置表單的MIME編碼)的表單數(shù)據(jù)蜕衡。
$ cnpm install body-parser --save
$ cnpm install cookie-parser --save
$ cnpm install multer --save
安裝完后,我們可以查看下 express 使用的版本號(hào):
$ cnpm list express
/data/www/node
└── express@4.15.2 -> /Users/tianqixin/www/node/node_modules/.4.15.2@express
02设拟、第一個(gè) Express 框架實(shí)例
接下來我們使用 Express 框架來輸出 "Hello World"慨仿。
以下實(shí)例中我們引入了 express 模塊久脯,并在客戶端發(fā)起請(qǐng)求后,響應(yīng) "Hello World" 字符串镰吆。
創(chuàng)建 express_demo.js 文件帘撰,代碼如下所示:
//express_demo.js 文件
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World');
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("應(yīng)用實(shí)例,訪問地址為 http://%s:%s", host, port)
})
執(zhí)行以上代碼:
$ node express_demo.js
應(yīng)用實(shí)例万皿,訪問地址為 http://0.0.0.0:8081
03摧找、請(qǐng)求和響應(yīng)
Express 應(yīng)用使用回調(diào)函數(shù)的參數(shù): request 和 response 對(duì)象來處理請(qǐng)求和響應(yīng)的數(shù)據(jù)。
app.get('/', function (req, res) {
// --
})
request 和 response 對(duì)象的具體介紹:
Request 對(duì)象 - request 對(duì)象表示 HTTP 請(qǐng)求牢硅,包含了請(qǐng)求查詢字符串蹬耘,參數(shù),內(nèi)容减余,HTTP 頭部等屬性综苔。常見屬性有:
req.app:當(dāng)callback為外部文件時(shí),用req.app訪問express的實(shí)例
req.baseUrl:獲取路由當(dāng)前安裝的URL路徑
req.body / req.cookies:獲得「請(qǐng)求主體」/ Cookies
req.fresh / req.stale:判斷請(qǐng)求是否還「新鮮」
req.hostname / req.ip:獲取主機(jī)名和IP地址
req.originalUrl:獲取原始請(qǐng)求URL
req.params:獲取路由的parameters
req.path:獲取請(qǐng)求路徑
req.protocol:獲取協(xié)議類型
req.query:獲取URL的查詢參數(shù)串
req.route:獲取當(dāng)前匹配的路由
req.subdomains:獲取子域名
req.accepts():檢查可接受的請(qǐng)求的文檔類型
req.acceptsCharsets / req.acceptsEncodings / req.acceptsLanguages:返回指定字符集的第一個(gè)可接受字符編碼
req.get():獲取指定的HTTP請(qǐng)求頭
req.is():判斷請(qǐng)求頭Content-Type的MIME類型
Response 對(duì)象 - response 對(duì)象表示 HTTP 響應(yīng)位岔,即在接收到請(qǐng)求時(shí)向客戶端發(fā)送的 HTTP 響應(yīng)數(shù)據(jù)休里。常見屬性有:
res.app:同req.app一樣
res.append():追加指定HTTP頭
res.set()在res.append()后將重置之前設(shè)置的頭
res.cookie(name,value [赃承,option]):設(shè)置Cookie
opition: domain / expires / httpOnly / maxAge / path / secure / signed
res.clearCookie():清除Cookie
res.download():傳送指定路徑的文件
res.get():返回指定的HTTP頭
res.json():傳送JSON響應(yīng)
res.jsonp():傳送JSONP響應(yīng)
res.location():只設(shè)置響應(yīng)的Location HTTP頭妙黍,不設(shè)置狀態(tài)碼或者close response
res.redirect():設(shè)置響應(yīng)的Location HTTP頭,并且設(shè)置狀態(tài)碼302
res.send():傳送HTTP響應(yīng)
res.sendFile(path [瞧剖,options] [拭嫁,fn]):傳送指定路徑的文件 -會(huì)自動(dòng)根據(jù)文件extension設(shè)定Content-Type
res.set():設(shè)置HTTP頭,傳入object可以一次設(shè)置多個(gè)頭
res.status():設(shè)置HTTP狀態(tài)碼
res.type():設(shè)置Content-Type的MIME類型
04抓于、路由
我們已經(jīng)了解了 HTTP 請(qǐng)求的基本應(yīng)用做粤,而路由決定了由誰(指定腳本)去響應(yīng)客戶端請(qǐng)求。
在HTTP請(qǐng)求中捉撮,我們可以通過路由提取出請(qǐng)求的URL以及GET/POST參數(shù)怕品。
接下來我們擴(kuò)展 Hello World,添加一些功能來處理更多類型的 HTTP 請(qǐng)求巾遭。
創(chuàng)建 express_demo2.js 文件肉康,代碼如下所示:
var express = require('express');
var app = express();
// 主頁輸出 "Hello World"
app.get('/', function (req, res) {
console.log("主頁 GET 請(qǐng)求");
res.send('Hello GET');
})
// POST 請(qǐng)求
app.post('/', function (req, res) {
console.log("主頁 POST 請(qǐng)求");
res.send('Hello POST');
})
// /del_user 頁面響應(yīng)
app.get('/del_user', function (req, res) {
console.log("/del_user 響應(yīng) DELETE 請(qǐng)求");
res.send('刪除頁面');
})
// /list_user 頁面 GET 請(qǐng)求
app.get('/list_user', function (req, res) {
console.log("/list_user GET 請(qǐng)求");
res.send('用戶列表頁面');
})
// 對(duì)頁面 abcd, abxcd, ab123cd, 等響應(yīng) GET 請(qǐng)求
app.get('/ab*cd', function(req, res) {
console.log("/ab*cd GET 請(qǐng)求");
res.send('正則匹配');
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("應(yīng)用實(shí)例,訪問地址為 http://%s:%s", host, port)
})
執(zhí)行以上代碼:
$ node express_demo2.js
應(yīng)用實(shí)例灼舍,訪問地址為 http://0.0.0.0:8081
05吼和、靜態(tài)文件
Express 提供了內(nèi)置的中間件 express.static 來設(shè)置靜態(tài)文件如:圖片, CSS, JavaScript 等骑素。
你可以使用 express.static 中間件來設(shè)置靜態(tài)文件路徑炫乓。例如,如果你將圖片, CSS, JavaScript 文件放在 public 目錄下末捣,你可以這么寫:
app.use(express.static('public'));
我們可以到 public/images 目錄下放些圖片,如下所示:
node_modules
server.js
public/
public/images
public/images/logo.png
讓我們?cè)傩薷南?"Hello World" 應(yīng)用添加處理靜態(tài)文件的功能侠姑。
創(chuàng)建 express_demo3.js 文件,代碼如下所示:
var express = require('express');
var app = express();
app.use(express.static('public'));
app.get('/', function (req, res) {
res.send('Hello World');
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("應(yīng)用實(shí)例箩做,訪問地址為 http://%s:%s", host, port)
})
結(jié)果:
$ node express_demo3.js
應(yīng)用實(shí)例结借,訪問地址為 http://0.0.0.0:8081
06、GET 方法
以下實(shí)例演示了在表單中通過 GET 方法提交兩個(gè)參數(shù)卒茬,我們可以使用 server.js 文件內(nèi)的 process_get 路由器來處理輸入
index.html文件
<html>
<body>
<form action="http://127.0.0.1:8081/process_get" method="GET">
First Name: <input type="text" name="first_name"> <br>
Last Name: <input type="text" name="last_name">
<input type="submit" value="Submit">
</form>
</body>
</html>
server.js
var express = require('express');
var app = express();
app.use(express.static('public'));
app.get('/index.htm', function (req, res) {
res.sendFile( __dirname + "/" + "index.htm" );
})
app.get('/process_get', function (req, res) {
// 輸出 JSON 格式
var response = {
"first_name":req.query.first_name,
"last_name":req.query.last_name
};
console.log(response);
res.end(JSON.stringify(response));
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("應(yīng)用實(shí)例,訪問地址為 http://%s:%s", host, port)
})
執(zhí)行以上代碼:
node server.js
應(yīng)用實(shí)例咖熟,訪問地址為 http://0.0.0.0:8081
07圃酵、POST 方法
以下實(shí)例演示了在表單中通過 POST 方法提交兩個(gè)參數(shù),我們可以使用 server.js 文件內(nèi)的 process_post 路由器來處理輸入:
index.html
<html>
<body>
<form action="http://127.0.0.1:8081/process_post" method="POST">
First Name: <input type="text" name="first_name"> <br>
Last Name: <input type="text" name="last_name">
<input type="submit" value="Submit">
</form>
</body>
</html>
server.js
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
// 創(chuàng)建 application/x-www-form-urlencoded 編碼解析
var urlencodedParser = bodyParser.urlencoded({ extended: false })
app.use(express.static('public'));
app.get('/index.htm', function (req, res) {
res.sendFile( __dirname + "/" + "index.htm" );
})
app.post('/process_post', urlencodedParser, function (req, res) {
// 輸出 JSON 格式
var response = {
"first_name":req.body.first_name,
"last_name":req.body.last_name
};
console.log(response);
res.end(JSON.stringify(response));
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("應(yīng)用實(shí)例馍管,訪問地址為 http://%s:%s", host, port)
})
執(zhí)行以上代碼:
$ node server.js
應(yīng)用實(shí)例郭赐,訪問地址為 http://0.0.0.0:8081
08、文件上傳
以下我們創(chuàng)建一個(gè)用于上傳文件的表單确沸,使用 POST 方法捌锭,表單 enctype 屬性設(shè)置為 multipart/form-data。
<html>
<head>
<title>文件上傳表單</title>
</head>
<body>
<h3>文件上傳:</h3>
選擇一個(gè)文件上傳: <br />
<form action="/file_upload" method="post" enctype="multipart/form-data">
<input type="file" name="image" size="50" />
<br />
<input type="submit" value="上傳文件" />
</form>
</body>
</html>
server.js
<pre>
var express = require('express');
var app = express();
var fs = require("fs");
var bodyParser = require('body-parser');
var multer = require('multer');
app.use(express.static('public'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(multer({ dest: '/tmp/'}).array('image'));
app.get('/index.htm', function (req, res) {
res.sendFile( __dirname + "/" + "index.htm" );
})
app.post('/file_upload', function (req, res) {
console.log(req.files[0]); // 上傳的文件信息
var des_file = __dirname + "/" + req.files[0].originalname;
fs.readFile( req.files[0].path, function (err, data) {
fs.writeFile(des_file, data, function (err) {
if( err ){
console.log( err );
}else{
response = {
message:'File uploaded successfully',
filename:req.files[0].originalname
};
}
console.log( response );
res.end( JSON.stringify( response ) );
});
});
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("應(yīng)用實(shí)例罗捎,訪問地址為 http://%s:%s", host, port)
})
09观谦、Cookie 管理
我們可以使用中間件向 Node.js 服務(wù)器發(fā)送 cookie 信息,以下代碼輸出了客戶端發(fā)送的 cookie 信息:
// express_cookie.js 文件
var express = require('express')
var cookieParser = require('cookie-parser')
var app = express()
app.use(cookieParser())
app.get('/', function(req, res) {
console.log("Cookies: ", req.cookies)
})
app.listen(8081)
------------------------------------------------RESTful API-----------------------------------------------------
什么是 REST桨菜?
REST即表述性狀態(tài)傳遞(英文:Representational State Transfer豁状,簡稱REST)是Roy Fielding博士在2000年他的博士論文中提出來的一種軟件架構(gòu)風(fēng)格。
表述性狀態(tài)轉(zhuǎn)移是一組架構(gòu)約束條件和原則倒得。滿足這些約束條件和原則的應(yīng)用程序或設(shè)計(jì)就是RESTful泻红。需要注意的是,REST是設(shè)計(jì)風(fēng)格而不是標(biāo)準(zhǔn)霞掺。REST通骋曷罚基于使用HTTP,URI菩彬,和XML(標(biāo)準(zhǔn)通用標(biāo)記語言下的一個(gè)子集)以及HTML(標(biāo)準(zhǔn)通用標(biāo)記語言下的一個(gè)應(yīng)用)這些現(xiàn)有的廣泛流行的協(xié)議和標(biāo)準(zhǔn)缠劝。REST 通常使用 JSON 數(shù)據(jù)格式。
HTTP 方法
以下為 REST 基本架構(gòu)的四個(gè)方法:
GET - 用于獲取數(shù)據(jù)骗灶。
PUT - 用于更新或添加數(shù)據(jù)剩彬。
DELETE - 用于刪除數(shù)據(jù)。
POST - 用于添加數(shù)據(jù)矿卑。
01喉恋、RESTful Web Services
Web service是一個(gè)平臺(tái)獨(dú)立的,低耦合的,自包含的轻黑、基于可編程的web的應(yīng)用程序糊肤,可使用開放的XML(標(biāo)準(zhǔn)通用標(biāo)記語言下的一個(gè)子集)標(biāo)準(zhǔn)來描述、發(fā)布氓鄙、發(fā)現(xiàn)馆揉、協(xié)調(diào)和配置這些應(yīng)用程序,用于開發(fā)分布式的互操作的應(yīng)用程序抖拦。
基于 REST 架構(gòu)的 Web Services 即是 RESTful升酣。
由于輕量級(jí)以及通過 HTTP 直接傳輸數(shù)據(jù)的特性,Web 服務(wù)的 RESTful 方法已經(jīng)成為最常見的替代方法态罪∝眩可以使用各種語言(比如 Java 程序、Perl复颈、Ruby绩聘、Python、PHP 和 Javascript[包括 Ajax])實(shí)現(xiàn)客戶端耗啦。
RESTful Web 服務(wù)通吃淦校可以通過自動(dòng)客戶端或代表用戶的應(yīng)用程序訪問。但是帜讲,這種服務(wù)的簡便性讓用戶能夠與之直接交互衅谷,使用它們的 Web 瀏覽器構(gòu)建一個(gè) GET URL 并讀取返回的內(nèi)容。
更多介紹似将,可以查看:RESTful 架構(gòu)詳解
02会喝、創(chuàng)建 RESTful
首先,創(chuàng)建一個(gè) json 數(shù)據(jù)資源文件 users.json玩郊,內(nèi)容如下:
{
"user1" : {
"name" : "mahesh",
"password" : "password1",
"profession" : "teacher",
"id": 1
},
"user2" : {
"name" : "suresh",
"password" : "password2",
"profession" : "librarian",
"id": 2
},
"user3" : {
"name" : "ramesh",
"password" : "password3",
"profession" : "clerk",
"id": 3
}
}
基于以上數(shù)據(jù)肢执,我們創(chuàng)建以下 RESTful API:
序號(hào) URI HTTP 方法 發(fā)送內(nèi)容 結(jié)果
1 listUsers GET 空 顯示所有用戶列表
2 addUser POST JSON 字符串 添加新用戶
3 deleteUser DELETE JSON 字符串 刪除用戶
4 :id GET 空 顯示用戶詳細(xì)信息
03、獲取用戶列表:
以下代碼译红,我們創(chuàng)建了 RESTful API listUsers预茄,用于讀取用戶的信息列表, server.js 文件代碼如下所示:
var express = require('express');
var app = express();
var fs = require("fs");
app.get('/listUsers', function (req, res) {
fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
console.log( data );
res.end( data );
});
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("應(yīng)用實(shí)例侦厚,訪問地址為 http://%s:%s", host, port)
})
接下來執(zhí)行以下命令:
$ node server.js
應(yīng)用實(shí)例耻陕,訪問地址為 http://0.0.0.0:8081
在瀏覽器中訪問 http://127.0.0.1:8081/listUsers,結(jié)果如下所示:
{
"user1" : {
"name" : "mahesh",
"password" : "password1",
"profession" : "teacher",
"id": 1
},
"user2" : {
"name" : "suresh",
"password" : "password2",
"profession" : "librarian",
"id": 2
},
"user3" : {
"name" : "ramesh",
"password" : "password3",
"profession" : "clerk",
"id": 3
}
}
04刨沦、添加用戶
以下代碼诗宣,我們創(chuàng)建了 RESTful API addUser, 用于添加新的用戶數(shù)據(jù)想诅,server.js 文件代碼如下所示:
var express = require('express');
var app = express();
var fs = require("fs");
//添加的新用戶數(shù)據(jù)
var user = {
"user4" : {
"name" : "mohit",
"password" : "password4",
"profession" : "teacher",
"id": 4
}
}
app.get('/addUser', function (req, res) {
// 讀取已存在的數(shù)據(jù)
fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
data = JSON.parse( data );
data["user4"] = user["user4"];
console.log( data );
res.end( JSON.stringify(data));
});
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("應(yīng)用實(shí)例召庞,訪問地址為 http://%s:%s", host, port)
})
接下來執(zhí)行以下命令:
$ node server.js
應(yīng)用實(shí)例岛心,訪問地址為 http://0.0.0.0:8081
在瀏覽器中訪問 http://127.0.0.1:8081/addUser,結(jié)果如下所示:
{ user1:
{ name: 'mahesh',
password: 'password1',
profession: 'teacher',
id: 1 },
user2:
{ name: 'suresh',
password: 'password2',
profession: 'librarian',
id: 2 },
user3:
{ name: 'ramesh',
password: 'password3',
profession: 'clerk',
id: 3 },
user4:
{ name: 'mohit',
password: 'password4',
profession: 'teacher',
id: 4 }
}
05篮灼、顯示用戶詳情
以下代碼忘古,我們創(chuàng)建了 RESTful API :id(用戶id), 用于讀取指定用戶的詳細(xì)信息诅诱,server.js 文件代碼如下所示:
var express = require('express');
var app = express();
var fs = require("fs");
app.get('/:id', function (req, res) {
// 首先我們讀取已存在的用戶
fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
data = JSON.parse( data );
var user = data["user" + req.params.id]
console.log( user );
res.end( JSON.stringify(user));
});
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("應(yīng)用實(shí)例髓堪,訪問地址為 http://%s:%s", host, port)
})
接下來執(zhí)行以下命令:
$ node server.js
應(yīng)用實(shí)例,訪問地址為 http://0.0.0.0:8081
在瀏覽器中訪問 http://127.0.0.1:8081/2娘荡,結(jié)果如下所示:
{
"name":"suresh",
"password":"password2",
"profession":"librarian",
"id":2
}
06干旁、刪除用戶
以下代碼,我們創(chuàng)建了 RESTful API deleteUser炮沐, 用于刪除指定用戶的詳細(xì)信息争群,以下實(shí)例中,用戶 id 為 2央拖,server.js 文件代碼如下所示:
var express = require('express');
var app = express();
var fs = require("fs");
var id = 2;
app.get('/deleteUser', function (req, res) {
// First read existing users.
fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
data = JSON.parse( data );
delete data["user" + 2];
console.log( data );
res.end( JSON.stringify(data));
});
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("應(yīng)用實(shí)例,訪問地址為 http://%s:%s", host, port)
})
接下來執(zhí)行以下命令:
$ node server.js
應(yīng)用實(shí)例鹉戚,訪問地址為 http://0.0.0.0:8081
在瀏覽器中訪問 http://127.0.0.1:8081/deleteUser鲜戒,結(jié)果如下所示:
{ user1:
{ name: 'mahesh',
password: 'password1',
profession: 'teacher',
id: 1 },
user3:
{ name: 'ramesh',
password: 'password3',
profession: 'clerk',
id: 3 }
}