Node.js輕量級Web框架Express4.x使用指南
Express是一個輕量級的Web框架,簡單、靈活
也是目前最流行的基於Nodejs的Web框架
通過它我們可以快速搭建功能完整的網站
(express 英文意思:特快列車)
Express現在是4.x版本,更新很快
並且不相容舊版本
導致現在市面上很多優秀的Node書籍過時
這篇文章是一篇入門級的Express使用,需要一定Node.js的基礎
Web應用建立
首先要做的是下載express並引用
npm install express --save
全域性安裝就+個-g
引用express
var express = require('express');
var app = express();
通過app我們就可以使用各種express的API
在3.x版本的時候是這樣寫的
var app =express.createServer();
現在這個函式已經被拋棄了
下面正式建立應用
//app.js
var express = require('express');
var app = express();
app.get('/', function(req, res){
res.send('Express');
});
app.listen(3000);
啟動之後就能給夠在頁面看到效果
$ node app.js
app.get()
上面的app.listen()就不多說了
用於監聽埠
app.get(path, function(req, res){ })
用於用於處理客戶端向伺服器傳送的GET請求
path表示請求的路徑
回撥函式的req和res是request和response的意思
request表示客戶端傳送的HTTP請求資訊
response表示伺服器傳送的HTTP響應資訊
使用res.send()可以向客戶端傳送資訊
//app.js
var express = require('express');
var app = express();
app.get ('/', function(req, res){
res.send('<h1>Express</h1>');
});
app.get('/demo', function(req, res){
res.send('<h1>Demo</h1>');
})
app.get('/*', function(req, res){
res.send('<h1>404<h1>');
})
app.listen(3000);
app.post()
app.post(path, function(req, res){ })
用於用於處理客戶端向伺服器傳送的POST請求
和GET請求不同,POST請求不會將資訊放在url中
而是寫入請求頭中
它的解析有所不同,下面再說
app.all()
在此之前還要提一個概念——中介軟體
Middleware中介軟體在不同環境下有不同含義
而在我們express中,簡單說它就是一個特殊的函式
用來處理HTTP請求的函式
並且它有一個特點——處理完一箇中間件可以傳遞給下一個中介軟體來處理
funciton(req, res, next){
...
next();
}
(如果不使用執行next函式,那麼之後監聽的函式也不會執行)
可以向next中傳遞字串引數,代表丟擲的錯誤資訊
這樣當資料往下傳遞的時候,中介軟體不再進行處理
直到找到一個錯誤處理函式為止
在app.all(path, function(req, res, next){ })
的使用中
就需要我們定義這樣的中介軟體
這個方法可以過濾所有路徑上的請求
換句話說,在其他所有的中介軟體處理之前
必須先通過app.all()的中介軟體進行處理
var express = require('express');
var app = express();
app.all('*', function(req, res, next){
res.writeHead(200, ':)');
next();
});
app.get('/', function(req, res){
res.end('<h1>Express</h1>');
});
app.get('/demo', function(req, res){
res.end('<h1>Demo</h1>');
})
app.get('/*', function(req, res){
res.end('<h1>404<h1>');
})
app.listen(3000);
這樣不論客戶端向我們發出了什麼樣的路徑請求
伺服器響應資訊前都會先打上響應頭
app.use()
app.use([path, ]function(req, res, next){ })
這個方法一般情況是用來呼叫中介軟體的
與前面的函式不同,它的第一個path引數可以省略,預設'/'
app.use(express.static(path.join(__dirname, '/public')));
上面的這個用法就是指定靜態檔案的訪問路徑
通過next引數我們可以連續呼叫中介軟體函式
app.use(function(req, res, next){
console.log(1);
next();
});
app.use(function(req, res, next){
console.log(2);
next();
});
app.use(function(req, res, next){
console.log(3);
});
app.use(function(req, res, next){
console.log(4);
});
當發出網路請求的時候
控制檯就會輸出 1 2 3
因為第三個中介軟體沒有呼叫next方法
所以處理到此為止
不會輸出4
app.use()除了呼叫中介軟體
還可以根據請求路徑的不同,返回不同資訊
但我們一般不會這麼用
//app.js
var express = require('express');
var app = express();
app.use(function(req, res, next){
if(req.url == '/'){
res.end('<h1>Express</h1>');
}else{
next();
}
});
app.use(function(req, res, next){
if(req.url == '/demo'){
res.end('<h1>Demo</h1>');
}else{
next();
}
});
app.use(function(req, res, next){
res.end('<h1>404<h1>');
});
app.listen(3000);
請求與響應
上面express中每一個回撥函式都不可缺少req和res引數
重要性可見一斑
常見的req與res中的屬性/方法如下(原生Node.js的req、res屬性/方法也可以使用)
Request物件:
API | 含義 |
---|---|
req.app |
當callback為外部檔案時,用於訪問express的例項 |
req.baseUrl |
獲取路由當前安裝的URL路徑 |
req.body/cookies |
獲得「請求主體」/ Cookies |
req.fresh/stale |
判斷請求是否還「新鮮」 |
req.hostname/ip |
獲取主機名和IP地址 |
req.originalUrl |
獲取原始請求URL |
req.params |
獲取路由的parameters |
req.path |
獲取請求路徑 |
req.protocol |
獲取協議型別 |
req.query |
獲取URL的查詢引數串 |
req.route |
獲取當前匹配的路由 |
req.subdomains |
獲取子域名 |
req.acceptsCharsets |
返回指定字符集的第一個可接受字元編碼 |
req.acceptsEncodings |
返回指定字符集的第一個可接受字元編碼 |
req.acceptsLanguages |
返回指定字符集的第一個可接受字元編碼 |
req.accepts() |
檢查可接受的請求的文件型別 |
req.get() |
獲取指定的HTTP請求頭 |
req.is() |
判斷請求頭Content-Type的MIME型別 |
Response物件:
API | 含義 |
---|---|
res.app |
同req.app |
res.append() |
追加指定HTTP頭 |
res.set() |
在res.append()後將重置之前設定的頭 |
res.cookie() |
設定Cookie |
res.clearCookie() |
清除Cookie |
res.download() |
傳送指定路徑的檔案 |
res.get() |
返回指定的HTTP頭 |
res.json() |
傳送JSON響應 |
res.jsonp() |
傳送JSONP響應 |
res.location() |
只設置響應的Location HTTP頭,不設定狀態碼或者close response |
res.redirect() |
設定響應的Location HTTP頭,並且設定狀態碼302 |
res.send() |
傳送HTTP響應 |
res.sendFile() |
傳送指定路徑的檔案 -會自動根據檔案extension設定Content-Type |
res.set() |
設定HTTP頭,傳入object可以一次設定多個頭 |
res.status() |
設定HTTP狀態碼 |
res.type() |
設定Content-Type的MIME型別 |
挑一些重點
req.query
req.query可以獲取請求路徑引數的物件
向伺服器傳送請求 http://localhost:3000/?user=tester&pass[a]=123&pass[b]=456
//app.js
var express = require('express');
var app = express();
app.get('/', function(req, res, next){
console.log(req.query);
console.log(req.query.user); //tester
console.log(req.query.pass.a); //123
console.log(req.query.pass.b); //456
res.end();
});
app.listen(3000);
req.params
req.params可以解析複雜路由規則上的屬性
(req.param綜合了req.query和req.param的功能,但是被移除了不要使用)
向伺服器傳送請求 http://localhost:3000/123456
//app.js
var express = require('express');
var app = express();
app.get('/:id', function(req, res, next){
console.log(req.params.id); //123456
res.end();
});
app.listen(3000);
這樣不論我在根路徑後輸入的是什麼
都會被解析為req.params.id
res.send()
res.send用於向客戶端響應資訊
並且它的強大之處在於可以智慧的處理我們傳遞的不同型別引數
app.get('/', function(req, res, next){
res.send('express');
});
當引數為字串,會將響應頭Content-Type預設設定為text/html
也就是解析為html呈現在我們的頁面上
app.get('/', function(req, res){
res.send(200);
});
當引數為數字,會自動幫我們設定響應體(狀態碼…)
app.get('/', function(req, res){
res.send([1, 2, 3]);
});
當引數為陣列或物件,它會響應一個JSON
res.redirect()
使用這個方法可以讓我們對網頁重定向
比如使用絕對url跳轉到不同的域名
app.get('/', function(req, res){
res.redirect('http://www.baidu.com');
});
res.redirect()預設響應狀態碼是302
可以更改這個狀態碼作為res.redirect()的第一個引數
//app.js
var express = require('express');
var app = express();
app.get('/', function(req, res){
res.redirect(302, 'demo');
});
app.get('/demo', function(req, res){
res.end();
});
app.listen(3000);
當在url位址列中輸入http://localhost:3000
頁面就會重定向到http://localhost:3000/demo
靜態資源
靜態資源就是指我們在開發中用到的css、js、img等等
它們需要存放到一個靜態資源目錄
當瀏覽器發出了一個非HTML檔案請求
伺服器就會從這個靜態資源目錄下去查詢檔案
我們一般在根目錄下建立一個public檔案來儲存
並在public中建立stylesheets、javascripts、images等資料夾
用來儲存特定型別的資源
指定靜態資源目錄的方法上面已經提到了
var path = require('path');
app.use(express.static(path.join(__dirname, 'public')));
比如說我們的html中有這樣的程式碼
<link href="/javascripts/jquery.js" rel="stylesheet" media="screen">
那麼客戶端執行發出請求
伺服器就會在public的javascripts資料夾下找到jquery.js靜態資源
模板引擎
express框架預設是ejs和jade渲染模板
這裡以jade為例
使用時肯定要下載
npm install jade --save
再通過app.set()指定查詢模板檔案的目錄(類似於靜態資源)
並指定模板檔案字尾為jade
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
(如果不使用模板而使用原生html,app.set('view engine', 'html');
)
如果我們想要訪問模板該怎麼做呢?
很簡單,只需要一個方法res.render()
現在我寫了一個簡單的jade模板(關於jade語法超出本文討論範圍)
//views/index.jade
doctype html
html
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
body
h1= title
p= content
通過res.render渲染
//app.js
var express = require('express');
var path = require('path');
var app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.get('/', function(req, res){
res.render('index', {
title: 'Express',
content: 'this is an example'
});
});
app.listen(3000);
res.render()
res.render(view[, datas][, callback])
用於對網頁模板進行渲染
第一個引數是要渲染的模板名稱
第二個引數是傳遞給模板的變數,以物件形式儲存,沒有可省略
第三個引數是渲染後回撥函式,可以省略
路由
路由的意思就是根據不同的路徑,來指定不同的處理方法
我們一般把不同的路由封裝進不同的模組
首先在根目錄下建立一個資料夾routes儲存路由
現在我在routes資料夾下建立倆個路由檔案index.js和users.js
修改app.js
//app.js
var express = require('express');
var path = require('path');
var app = express();
var index = require('./routes/index');
var users = require('./routes/users');
app.use('/', index);
app.use('/users', users);
app.listen(3000);
這樣表示http://localhost:3000/
的路由交給index處理
http://localhost:3000/users
的路由交給users處理
下面簡單的實現一下路由
//routes/index.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res){
res.end('index');
});
router.get('/123', function(){
res.end(123);
});
module.exports = router;
//routes/users.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.end('users');
});
module.exports = router;
通過express.Router()
建立的router就像一個mini版的app一樣
app能做的,router都能做
只是我們把邏輯都封裝到了各個路由模組中
上面程式碼的結果:
body-parser中介軟體
作為一個入門級文章
最後就來淺顯的談一箇中間件body-parser吧
其實express在3.x版本中內建了很多中介軟體
但是4.x版本就將出static以外的所有中介軟體全部抽離出來了
所以就需要我們單獨安裝
對照表如下:
Express 3.0 | Express 4.0 |
---|---|
bodyParser | body-parser |
compress | compression |
cookieSession | cookie-session |
logger | morgan |
cookieParser | cookie-parser |
session | express-session |
favicon | static-favicon |
response-time | response-time |
error-handler | errorhandler |
method-override | method-override |
timeout | connect-timeout |
vhost | vhost |
csrf | csurf |
剛才就提到了POST請求有所不同
不同的地方就在於我們需要body-parser這個中介軟體來處理資料
通過req.body來獲得資料
首先使用前不要忘記下載
npm install body-parser --save
//app.js
var express = require('express');
var bodyParser = require('body-parser');
var path = require('path');
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.get('/', function(req, res){
res.send('<form method="POST" action="./form">\
<input type="text" name="user">\
<input type="submit">\
</form>');
});
app.post('/form', function(req, res){
console.log(req.body);
var user = req.body.user;
res.send('賬號: ' + user);
});
app.listen(3000);
下面這四個方法分別用於對body內容採取不同的處理方法
bodyParser.json(options)
處理JSON資料bodyParser.raw(options)
處理buffer資料bodyParser.text(options)
處理文字資料bodyParser.urlencoded(options)
處理UTF-8編碼資料
這樣我首先通過get請求獲取主頁面
提交表單向伺服器傳送post請求
伺服器響應結果
express-generator
通過express-generator應用生成器
可以為我們快速生成專案雛形
在你要生成專案的目錄中下載express-generator
npm install express-generator
然後輸入
express <專案檔名>
這樣express就會把必要的資料夾以及程式碼快速生成了