express
第一個 express
開始
mkdir myapp
# 注意設置 默認啟動 js 為app.js
npm init
npm install express --save
創建 app.js
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
對所有 (/) URL 或 路由 返回 “Hello World!” 字符串。對于其他所有路徑全部返回 404 Not Found。
啟動
node app.js
使用express 應用生成器
安裝
npm install express-generator -g
# -h 選項可以列出所有可用的命令行選項:
express -h
創建
# 不需要創建myapp目錄,自動創建
express myapp
# 進入myapp 安裝依賴
cd myapp
npm install
# 啟動
DEBUG=myapp npm start
使用webstorm 創建項目
File--New--Project--Node.js Express App(左側)--配置blabla
express 路由
路由的定義由如下結構組成:app.METHOD(PATH, HANDLER)。其中,app 是一個 express 實例;METHOD 是某個 HTTP 請求方式中的一個;PATH 是服務器端的路徑;HANDLER 是當路由匹配到時需要執行的函數。
get, post, put, head, delete, options, trace, copy, lock, mkcol, move, purge, propfind, proppatch, unlock, report, mkactivity, checkout, merge, m-search, notify, subscribe, unsubscribe, patch, search, 和 connect。
有些路由方法名不是合規的 JavaScript 變量名,此時使用括號記法,比如: app['m-search']('/', function ...
示例[結合postman快速測試吧]:
// 對網站首頁的訪問返回 "Hello World!" 字樣
app.get('/', function (req, res) {
res.send('Hello World!');
});
// 網站首頁接受 POST 請求
app.post('/', function (req, res) {
res.send('Got a POST request');
});
// /user 節點接受 PUT 請求
app.put('/user', function (req, res) {
res.send('Got a PUT request at /user');
});
// /user 節點接受 DELETE 請求
app.delete('/user', function (req, res) {
res.send('Got a DELETE request at /user');
});
使用字符串模式的路由
在我理解來就是通配符。
// 匹配 acd 和 abcd
app.get('/ab?cd', function(req, res) {
res.send('ab?cd');
});
// 匹配 abcd、abbcd、abbbcd等
app.get('/ab+cd', function(req, res) {
res.send('ab+cd');
});
// 匹配 abcd、abxcd、abRABDOMcd、ab123cd等
app.get('/ab*cd', function(req, res) {
res.send('ab*cd');
});
// 匹配 /abe 和 /abcde
app.get('/ab(cd)?e', function(req, res) {
res.send('ab(cd)?e');
});
使用正則表達式的路由路徑
// 匹配任何路徑中含有 a 的路徑:
app.get(/a/, function(req, res) {
res.send('/a/');
});
// 匹配 butterfly、dragonfly,不匹配 butterflyman、dragonfly man等
app.get(/.*fly$/, function(req, res) {
res.send('/.*fly$/');
});
路由句柄
使用一個回調函數處理路由:
app.get('/example/a', function (req, res) {
res.send('Hello from A!');
});
使用多個回調函數處理路由(記得指定 next 對象):
app.get('/example/b', function (req, res, next) {
console.log('response will be sent by the next function ...');
next();
}, function (req, res) {
res.send('Hello from B!');
});
使用回調函數數組處理路由:
var cb0 = function (req, res, next) {
console.log('CB0');
next();
}
var cb1 = function (req, res, next) {
console.log('CB1');
next();
}
var cb2 = function (req, res) {
res.send('Hello from C!');
}
app.get('/example/c', [cb0, cb1, cb2]);
混合使用函數和函數數組處理路由:
var cb0 = function (req, res, next) {
console.log('CB0');
next();
}
var cb1 = function (req, res, next) {
console.log('CB1');
next();
}
app.get('/example/d', [cb0, cb1], function (req, res, next) {
console.log('response will be sent by the next function ...');
next();
}, function (req, res) {
res.send('Hello from D!');
});
響應方法
下表中響應對象(res)的方法向客戶端返回響應,終結請求響應的循環。如果在路由句柄中一個方法也不調用,來自客戶端的請求會一直掛起。
方法 | 描述 |
---|---|
res.download() | 提示下載文件 |
res.end() | 終結響應處理流程 |
res.json() | 發送一個JSON格式的響應 |
res.jsonp() | 發送一個支持JSONP的JSON格式的響應 |
res.redirect() | 重定向請求 |
res.render() | 渲染視圖模板 |
res.send() | 發送各種類型的響應 |
res.sendFile() | 以八位字節流的形式發送文件 |
res.sendStatus() | 設置響應狀態代碼,并將其以字符串形式作為響應體的一部分發送 |
app.route()
可使用 app.route() 創建路由路徑的鏈式路由句柄。由于路徑在一個地方指定,這樣做有助于創建模塊化的路由,而且減少了代碼冗余和拼寫錯誤。
app.route('/book')
.get(function(req, res) {
res.send('Get a random book');
})
.post(function(req, res) {
res.send('Add a book');
})
.put(function(req, res) {
res.send('Update the book');
});
express.Route
創建 birds.js
var express = require('express');
var router = express.Router();
// 該路由使用的中間件
router.use(function timeLog(req, res, next) {
console.log('Time: ', Date.now());
next();
});
// 定義網站主頁的路由
router.get('/', function(req, res) {
res.send('Birds home page');
});
// 定義 about 頁面的路由
router.get('/about', function(req, res) {
res.send('About birds');
});
module.exports = router;
然后在應用中加載路由模塊
var birds = require('./birds');
...
app.use('/birds', birds);
應用即可處理發自 /birds 和 /birds/about 的請求,并且調用為該路由指定的 timeLog 中間件。
利用Express托管靜態文件
通過 Express 內置的 express.static 可以方便地托管靜態文件,例如圖片、CSS、JavaScript 文件等。
app.use(express.static('public'));
現在,public 目錄下面的文件就可以訪問了。
//訪問
http://localhost:3000/images/kitten.jpg
如果你的靜態資源存放在多個目錄下面,你可以多次調用 express.static 中間件:
app.use(express.static('public'));
app.use(express.static('files'));
也可以
app.use('/static', express.static('public'));
//訪問
http://localhost:3000/static/images/kitten.jpg
渲染 html
res.sendFile();
使用中間件
Express 是一個自身功能極簡,完全是由路由和中間件構成一個的 web 開發框架:從本質上來說,一個 Express 應用就是在調用各種中間件。
中間件是一個函數,它可以訪問請求對象req,響應對象res,和web應用中處于請求-響應循環流程中的中間件,一般被命名為next的變量。
中間件的功能:
- 執行任何代碼
- 修改請求和響應對象
- 終結請求-響應循環
- 調用堆棧中的下一個中間件
如果當前中間件沒有終結請求-響應循環,則必須調用 next() 方法將控制權交給下一個中間件,否則請求就會掛起。
應用級中間件
應用級中間件綁定到 app 對象 使用 app.use() 和 app.METHOD(), 其中, METHOD 是需要處理的 HTTP 請求的方法,例如 GET, PUT, POST 等等,全部小寫。例如:
var app = express();
// 沒有掛載路徑的中間件,應用的每個請求都會執行該中間件
app.use(function (req, res, next) {
console.log('Time:', Date.now());
next();
});
// 掛載至 /user/:id 的中間件,任何指向 /user/:id 的請求都會執行它
app.use('/user/:id', function (req, res, next) {
console.log('Request Type:', req.method);
next();
});
// 路由和句柄函數(中間件系統),處理指向 /user/:id 的 GET 請求
app.get('/user/:id', function (req, res, next) {
res.send('USER');
});
如果需要在中間件棧中跳過剩余中間件,調用 next('route') 方法將控制權交給下一個路由。
// 一個中間件棧,處理指向 /user/:id 的 GET 請求
app.get('/user/:id', function (req, res, next) {
// 如果 user id 為 0, 跳到下一個路由
if (req.params.id == 0) next('route');
// 否則將控制權交給棧中下一個中間件
else next(); //
}, function (req, res, next) {
// 渲染常規頁面
res.render('regular');
});
// 處理 /user/:id, 渲染一個特殊頁面
app.get('/user/:id', function (req, res, next) {
res.render('special');
});
路由級中間件
var app = express();
var router = express.Router();
// 沒有掛載路徑的中間件,通過該路由的每個請求都會執行該中間件
router.use(function (req, res, next) {
console.log('Time:', Date.now());
next();
});
// 一個中間件棧,顯示任何指向 /user/:id 的 HTTP 請求的信息
router.use('/user/:id', function(req, res, next) {
console.log('Request URL:', req.originalUrl);
next();
}, function (req, res, next) {
console.log('Request Type:', req.method);
next();
});
// 一個中間件棧,處理指向 /user/:id 的 GET 請求
router.get('/user/:id', function (req, res, next) {
// 如果 user id 為 0, 跳到下一個路由
if (req.params.id == 0) next('route');
// 負責將控制權交給棧中下一個中間件
else next(); //
}, function (req, res, next) {
// 渲染常規頁面
res.render('regular');
});
// 處理 /user/:id, 渲染一個特殊頁面
router.get('/user/:id', function (req, res, next) {
console.log(req.params.id);
res.render('special');
});
// 將路由掛載至應用
app.use('/', router);
錯誤處理中間件
錯誤處理中間件有 4 個參數,定義錯誤處理中間件時必須使用這 4 個參數。即使不需要 next 對象,也必須在簽名中聲明它,否則中間件會被識別為一個常規中間件,不能處理錯誤。
錯誤處理中間件和其他中間件定義類似,只是要使用 4 個參數,而不是 3 個,其簽名如下: (err, req, res, next)。
app.use(function(err, req, res, next) {
console.error(err.stack);
res.status(500).send('Something broke!');
});
處理404
app.use(function(req, res, next) {
res.status(404).send('Sorry cant find that!');
});
內置中間件
express.static(root, [options])
express.static 是 Express 唯一內置的中間件。它基于 serve-static,負責在 Express 應用中提托管靜態資源。
app.use(express.static('public'));
app.use(express.static('uploads'));
app.use(express.static('files'));
帶選項的 官網
var options = {
dotfiles: 'ignore',
etag: false,
extensions: ['htm', 'html'],
index: false,
maxAge: '1d',
redirect: false,
setHeaders: function (res, path, stat) {
res.set('x-timestamp', Date.now());
}
}
app.use(express.static('public', options));
第三方中間件
例如:
//安裝
npm install cookie-parser
var express = require('express');
var app = express();
var cookieParser = require('cookie-parser');
// 加載用于解析 cookie 的中間件
app.use(cookieParser());
模板引擎
需要在應用中進行如下設置才能讓 Express 渲染模板文件:
views, 放模板文件的目錄,比如: app.set('views', './views')
view engine, 模板引擎,比如: app.set('view engine', 'jade')
然后安裝相應的模板引擎 npm 軟件包。
npm install jade --save