[1]概述 [2]入門實例 [3]生成器 [4]HTTP模塊 [5]中間件 [6]托管靜態資源 [7]常用中間件 [8]路由 [9]路由器實例 [10]響應方法 [11]請求方法 [12]APP方法 [13]HTTPS [14]模板引擎 [15]資料庫 [16]上傳文件 [17]開發實例 ...
前面的話
Express是一個簡潔、靈活的 node.js Web 應用開發框架, 它提供一系列強大的特性,幫助開發者創建各種 Web 和移動設備應用。本文將詳細介紹express框架
概述
官網對Express的描述,它是一個基於 Node.js 平臺,快速、開放、極簡的 web 開發框架。優點是易上手、高性能、擴展性強
1、易上手:nodejs最初就是為了開發高性能web伺服器而被設計出來的,然而相對底層的API會讓不少新手望而卻步。express對web開發相關的模塊進行了適度的封裝,屏蔽了大量複雜繁瑣的技術細節,讓開發者只需要專註於業務邏輯的開發,極大的降低了入門和學習的成本
2、高性能:Express僅在web應用相關的nodejs模塊上進行了適度的封裝和擴展,較大程度避免了過度封裝導致的性能損耗
3、擴展性強:基於中間件的開發模式,使得express應用的擴展、模塊拆分非常簡單,既靈活,擴展性又強
【安裝】
安裝express前,首先安裝nodejs,接下來為應用創建一個目錄,然後進入此目錄並將其作為當前工作目錄
$ mkdir myapp
$ cd myapp
通過 npm init 命令為應用創建一個 package.json 文件
$ npm init
此命令要求輸入幾個參數,例如應用的名稱和版本。 直接按“回車”鍵接受預設設置即可,下麵這個除外:
entry point: (index.js)
鍵入 app.js 或者所希望的名稱,這是當前應用的入口文件。如果希望採用預設的 index.js 文件名,只需按“回車”鍵即可
接下來安裝 Express 並將其保存到依賴列表中:
$ npm install express --save
如果只是臨時安裝 Express,不想將它添加到依賴列表中,只需略去 --save 參數即可:
$ npm install express
入門實例
在項目根目錄下,新建一個啟動文件,假定叫做index.js,新建一個public文件夾,併在public目錄下,新建index.html
var express = require('express'); var app = express(); app.use(express.static(__dirname + '/public')); app.listen(8080);
運行index.js後,訪問http://localhost:8080
,它會在瀏覽器中打開public目錄的index.html文件
當然,也可以在index.js之中,生成動態網頁
// index.js var express = require('express'); var app = express(); app.get('/', function (req, res) { res.send('Hello world!'); }); app.listen(3000);
運行index.js文件後,會在本機的3000埠啟動一個網站,網頁顯示Hello World
啟動腳本index.js的app.get
方法,用於指定不同的訪問路徑所對應的回調函數,這叫做“路由”(routing)。上面代碼只指定了根目錄的回調函數,因此只有一個路由記錄。實際應用中,可能有多個路由記錄
var express = require('express'); var app = express(); app.get('/', function (req, res) { res.send('Hello world!'); }); app.get('/customer', function(req, res){ res.send('customer page'); }); app.get('/admin', function(req, res){ res.send('admin page'); }); app.listen(3000);
這時,最好就把路由放到一個單獨的文件中,比如新建一個routes子目錄
// routes/index.js module.exports = function (app) { app.get('/', function (req, res) { res.send('Hello world'); }); app.get('/customer', function(req, res){ res.send('customer page'); }); app.get('/admin', function(req, res){ res.send('admin page'); }); };
然後,原來的index.js就變成下麵這樣
// index.js var express = require('express'); var app = express(); var routes = require('./routes')(app); app.listen(3000);
生成器
通過應用生成器工具 express
可以快速創建一個應用的骨架
[註意]一定要使用全局模式安裝express-generator,否則無法使用express命令
$ npm install express-generator -g
-h
選項可以列出所有可用的命令行選項:
$ express -h Usage: express [options] [dir] Options: -h, --help output usage information -V, --version output the version number -e, --ejs add ejs engine support (defaults to jade) --hbs add handlebars engine support -H, --hogan add hogan.js engine support -c, --css <engine> add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain css) --git add .gitignore -f, --force force on non-empty directory
例如,下麵的示例就是在當前工作目錄下創建一個命名為 myapp 的應用
$ express myapp create : myapp create : myapp/package.json create : myapp/app.js create : myapp/public create : myapp/public/javascripts create : myapp/public/images create : myapp/routes create : myapp/routes/index.js create : myapp/routes/users.js create : myapp/public/stylesheets create : myapp/public/stylesheets/style.css create : myapp/views create : myapp/views/index.jade create : myapp/views/layout.jade create : myapp/views/error.jade create : myapp/bin create : myapp/bin/www
然後安裝所有依賴包:
$ cd myapp
$ npm instal
啟動這個應用(MacOS 或 Linux 平臺):
$ DEBUG=myapp npm start
Windows 平臺使用如下命令:
> set DEBUG=myapp & npm start
然後在瀏覽器中打開 http://localhost:3000/
網址就可以看到這個應用了。i
通過 Express 應用生成器創建的應用一般都有如下目錄結構:
.
├── app.js
├── bin
│ └── www
├── package.json
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
│ └── style.css
├── routes
│ ├── index.js
│ └── users.js
└── views
├── error.jade
├── index.jade
└── layout.jade
7 directories, 9 files
HTTP模塊
Express框架建立在node.js內置的http模塊上。http模塊生成伺服器的原始代碼如下
var http = require("http"); var app = http.createServer(function(request, response) { response.writeHead(200, {"Content-Type": "text/plain"}); response.end("Hello world!"); }); app.listen(3000, "localhost");
上面代碼的關鍵是http模塊的createServer方法,表示生成一個HTTP伺服器實例。該方法接受一個回調函數,該回調函數的參數,分別為代表HTTP請求和HTTP回應的request對象和response對象。
Express框架的核心是對http模塊的再包裝。上面的代碼用Express改寫如下
var express = require('express'); var app = express(); app.get('/', function (req, res) { res.send('Hello world!'); }); app.listen(3000);
比較兩段代碼,可以看到它們非常接近。原來是用http.createServer
方法新建一個app實例,現在則是用Express的構造方法,生成一個Epress實例。兩者的回調函數都是相同的。Express框架等於在http模塊之上,加了一個中間層
中間件
【概述】
Express 是一個自身功能極簡,完全是由路由和中間件構成一個的 web 開發框架:從本質上來說,一個 Express 應用就是在調用各種中間件
簡單說,中間件(middleware)就是處理HTTP請求的函數。它最大的特點就是,一個中間件處理完,再傳遞給下一個中間件。App實例在運行過程中,會調用一系列的中間件
每個中間件可以從App實例,接收三個參數,依次為request對象(代表HTTP請求)、response對象(代表HTTP回應),next回調函數(代表下一個中間件)。每個中間件都可以對HTTP請求(request對象)進行加工,並且決定是否調用next方法,將request對象再傳給下一個中間件
中間件的功能包括:1、執行任何代碼;2、修改請求和響應對象;3、終結請求-響應迴圈;4、調用堆棧中的下一個中間件
如果當前中間件沒有終結請求-響應迴圈,則必須調用 next() 方法將控制權交給下一個中間件,否則請求就會掛起
一個不進行任何操作、只傳遞request對象的中間件,就是下麵這樣
function uselessMiddleware(req, res, next) { next(); }
上面代碼的next就是下一個中間件。如果它帶有參數,則代表拋出一個錯誤,參數為錯誤文本
function uselessMiddleware(req, res, next) { next('出錯了!'); }
拋出錯誤以後,後面的中間件將不再執行,直到發現一個錯誤處理函數為止
【分類】
Express 應用可使用如下幾種中間件:1、應用級中間件;2、路由級中間件;3、錯誤處理中間件;4、內置中間件;5、第三方中間件
1、應用級中間件綁定到 app 對象 使用 app.use() 和 app.METHOD(),其中, METHOD 是需要處理的 HTTP 請求的方法,例如 GET, PUT, POST 等等,全部小寫
2、路由級中間件綁定的對象為 express.Router()
3、錯誤處理中間件和其他中間件定義類似,只是要使用 4 個參數,而不是 3 個,其簽名如下: (err, req, res, next)
app.use(function(err, req, res, next) { console.error(err.stack); res.status(500).send('Something broke!'); });
4、express.static
是 Express 唯一內置的中間件。它基於 serve-static,負責在 Express 應用中提托管靜態資源
5、通過使用第三方中間件從而為 Express 應用增加更多功能。安裝所需功能的 node 模塊,併在應用中載入,可以在應用級載入,也可以在路由級載入。下麵的例子安裝並載入了一個解析 cookie 的中間件: cookie-parser
$ npm install cookie-parser
var express = require('express'); var app = express(); var cookieParser = require('cookie-parser'); // 載入用於解析 cookie 的中間件 app.use(cookieParser());
【use方法】
use是express註冊中間件的方法,它返回一個函數。下麵是一個連續調用兩個中間件的例子
var express = require("express"); var http = require("http"); var app = express(); app.use(function(request, response, next) { console.log("In comes a " + request.method + " to " + request.url); next(); }); app.use(function(request, response) { response.writeHead(200, { "Content-Type": "text/plain" }); response.end("Hello world!\n"); }); http.createServer(app).listen(1337);
上面代碼使用app.use
方法,註冊了兩個中間件。收到HTTP請求後,先調用第一個中間件,在控制台輸出一行信息,然後通過next
方法,將執行權傳給第二個中間件,輸出HTTP回應。由於第二個中間件沒有調用next
方法,所以request對象就不再向後傳遞了。
use
方法內部可以對訪問路徑進行判斷,據此實現簡單的路由,根據不同的請求網址,返回不同的網頁內容
var express = require("express"); var http = require("http"); var app = express(); app.use(function(request, response, next) { if (request.url == "/") { response.writeHead(200, { "Content-Type": "text/plain" }); response.end("Welcome to the homepage!\n"); } else { next(); } }); app.use(function(request, response, next) { if (request.url == "/about") { response.writeHead(200, { "Content-Type": "text/plain" }); } else { next(); } }); app.use(function(request, response) { response.writeHead(404, { "Content-Type": "text/plain" }); response.end("404 error!\n"); }); http.createServer(app).listen(1337);
上面代碼通過request.url
屬性,判斷請求的網址,從而返回不同的內容。註意,app.use
方法一共登記了三個中間件,只要請求路徑匹配,就不會將執行權交給下一個中間件。因此,最後一個中間件會返回404錯誤,即前面的中間件都沒匹配請求路徑,找不到所要請求的資源。
除了在回調函數內部判斷請求的網址,use方法也允許將請求網址寫在第一個參數。這代表,只有請求路徑匹配這個參數,後面的中間件才會生效。無疑,這樣寫更加清晰和方便
app.use('/path', someMiddleware);
上面代碼表示,只對根目錄的請求,調用某個中間件。
因此,上面的代碼可以寫成下麵的樣子
var express = require("express"); var http = require("http"); var app = express(); app.use("/home", function(request, response, next) { response.writeHead(200, { "Content-Type": "text/plain" }); response.end("Welcome to the homepage!\n"); }); app.use("/about", function(request, response, next) { response.writeHead(200, { "Content-Type": "text/plain" }); response.end("Welcome to the about page!\n"); }); app.use(function(request, response) { response.writeHead(404, { "Content-Type": "text/plain" }); response.end("404 error!\n"); }); http.createServer(app).listen(1337);
托管靜態資源
上面介紹了, express.static
是 Express 唯一內置的中間件,負責在 Express 應用中提托管靜態資源,例如圖片、CSS、JavaScript 文件等
express.static(root, [options])
參數 root
指提供靜態資源的根目錄,可選的 options
參數擁有如下屬性
屬性 類型 預設值 描述 dotfiles String “ignore” 是否對外輸出文件名以點開頭的文件。可選值為allow、deny和ignore etag Boolean true 是否啟用 etag 生成 extensions Array [] 設置文件擴展名備份選項 index Mixed “index.html” 發送目錄索引文件,設置為 false 禁用目錄索引。 lastModified Boolean true 設置Last-Modified頭為文件在操作系統上的最後修改日期。可選值為true或false maxAge Number 0 以毫秒或者其字元串格式設置 Cache-Control 頭的 max-age 屬性。 redirect Boolean true 當路徑為目錄時,重定向至 “/”。 setHeaders Function 設置 HTTP 頭以提供文件的函數。
var options = { 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));
一般地,如果不需要特殊的設置,將靜態資源文件所在的目錄作為參數傳遞給 express.static
中間件就可以提供靜態資源文件的訪問了。例如,假設在 public
目錄放置了圖片、CSS 和 JavaScript 文件
app.use(express.static('public'));
現在,public
目錄下麵的文件就可以訪問了
http://localhost:3000/images/kitten.jpg http://localhost:3000/css/style.css http://localhost:3000/js/app.js http://localhost:3000/images/bg.png http://localhost:3000/hello.html
如果靜態資源存放在多個目錄下麵,可以多次調用 express.static
中間件:
app.use(express.static('public'));
app.use(express.static('files'));
訪問靜態資源文件時,express.static
中間件會根據目錄添加的順序查找所需的文件。
如果希望所有通過 express.static
訪問的文件都存放在一個“虛擬(virtual)”目錄(即目錄根本不存在)下麵,可以通過為靜態資源目錄指定一個掛載路徑的方式來實現,如下所示:
app.use('/static', express.static('public'));
現在,可以通過帶有 “/static” 首碼的地址來訪問 public
目錄下麵的文件了
http://localhost:3000/static/images/kitten.jpg http://localhost:3000/static/css/style.css http://localhost:3000/static/js/app.js http://localhost:3000/static/images/bg.png http://localhost:3000/static/hello.html
常用中間件
【cookie-parser()】
用於解析cookie的中間件,添加中間後,req具備cookies屬性。通過req.cookies.xxx
可以訪問cookie的值
$ npm install cookie-parser
var cookieParser = require('cookie-parser') app.use(cookieParser(secret, options))
secret
是可選參數,用於對cookie進行簽名
,通過它可以判斷出客戶是否修改了cookie,這是處於安全考慮,這個參數是任意字元串
options
可選參數,是一個json對象,可選項包括path、expires、maxAge、domain、secure、httpOnly
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(8080)
【express-session】
session運行在伺服器端,當客戶端第一次訪問伺服器時,可以將客戶的登錄信息保存。 當客戶訪問其他頁面時,可以判斷客戶的登錄狀態,做出提示,相當於登錄攔截。session可以和Redis或者資料庫等結合做持久化操作,當伺服器掛掉時也不會導致某些客戶信息(購物車)丟失。
當瀏覽器訪問伺服器併發送第一次請求時,伺服器端會創建一個session對象,生成一個類似於key,value的鍵值對, 然後將key(cookie)返回到瀏覽器(客戶)端,瀏覽器下次再訪問時,攜帶key(cookie),找到對應的session(value)
。客戶的信息都保存在session中
$ npm install express-session
var express = require('express') var session = require('express-session') var app = express() app.use(session(options))
options 常用選項如下:
name - 預設'connect.sid',可自定義
store - session 儲存器實例
secret - 用於對cookie進行簽名
,通過它可以判斷出客戶是否修改了cookie,這是處於安全考慮,這個參數是任意字元串
cookie - 對session cookie的設置 。預設值 { path: '/', httpOnly: true, secure: false, maxAge: null }
genid - 是個函數,調用它來生成一個新的會話ID。 (預設:使用UID2庫)
rolling - 強制對每個響應的Cookie,重置到期日期。 (預設:false)
resave - 每一次都重新保存,即使沒修改過(預設:true)
proxy - ture/false,是否支持trust proxy
,,需要設置 app.enable('trust proxy');
一般來說,無需設置
常用方法如下:
Session.destroy()
:刪除session,當檢測到客戶端關閉時調用
Session.reload()
:當session有修改時,刷新session
Session.regenerate()
:將已有session初始化
Session.save()
:保存session
var express = require('express'); var cookieParser = require('cookie-parser'); var session = require('express-session'); app.use(cookieParser('sessiontest')); app.use(session({ secret: 'sessiontest',//與cookieParser中的一致 resave: true, saveUninitialized:true }));
//修改router/index.js,第一次請求時保存一條用戶信息。 router.get('/', function(req, res, next) { var user={ name:"Chen-xy", age:"22", address:"bj" } req.session.user=user; res.render('index', { title: 'the test for nodejs session' , name:'sessiontest' }); });
//修改router/users.js,判斷用戶是否登陸。 router.get('/', function(req, res, next) { if(req.session.user){ var user=req.session.user; var name=user.name; res.send('你好'+name+',歡迎來到我的家園。'); }else{ res.send('你還沒有登錄,先登錄下再試試!'); } });
【serve-favicon】
設置網站的 favicon圖標
$ npm install serve-favicon
var express = require('express') var favicon = require('serve-favicon') var path = require('path') var app = express() app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))) // Add your routes here, etc. app.listen(3000)
【body-parser】
bodyParser用於解析客戶端請求的body中的內容,內部使用JSON編碼處理,url編碼處理以及對於文件的上傳處理
$ npm install body-parser
var bodyParser = require('body-parser')
1、底層中間件用法:這將攔截和解析所有的請求;也即這種用法是全局的。
var express = require('express') var bodyParser = require('body-parser') var app = express() // parse application/x-www-form-urlencoded app.use(bodyParser.urlencoded({ extended: false })) // parse application/json app.use(bodyParser.json()) app.use(function (req, res) { res.setHeader('Content-Type', 'text/plain') res.write('you posted:\n') res.end(JSON.stringify(req.body, null, 2)) })
use方法調用body-parser實例;且use方法沒有設置路由路徑;這樣的body-parser實例就會對該app所有的請求進行攔截和解析
2、特定路由下的中間件用法:這種用法是針對特定路由下的特定請求的,只有請求該路由時,中間件才會攔截和解析該請求;也即這種用法是局部的;也是最常用的一個方式
var express = require('express') var bodyParser = require('body-parser') var app = express() // create application/json parser var jsonParser = bodyParser.json() // create application/x-www-form-urlencoded parser var urlencodedParser = bodyParser.urlencoded({ extended: false }) // POST /login gets urlencoded bodies app.post('/login', urlencodedParser, function (req, res) { if (!req.body) return res.sendStatus(400) res.send('welcome, ' + req.body.username) }) // POST /api/users gets JSON bodies app.post('/api/users', jsonParser, function (req, res) { if (!req.body) return res.sendStatus(400) // create user in req.body })
express的post(或者get)方法調用body-parser實例;且該方法有設置路由路徑;這樣的body-parser實例就會對該post(或者get)的請求進行攔截和解析
3、設置Content-Type 屬性;用於修改和設定中間件解析的body內容類型
// parse various different custom JSON types as JSON app.use(bodyParser.json({ type: 'application/*+json' }); // parse some custom thing into a Buffer app.use(bodyParser.raw({ type: 'application/vnd.custom-type' })); // parse an HTML body into a string app.use(bodyParser.text({ type: 'text/html' }));
【morgan】
Mogran是一個node.js關於http請求的express預設的日誌中間件
npm install morgan
在basic.js
中添加如下代碼
var express = require('express'); var app = express(); var morgan = require('morgan'); app.use(morgan('short')); app.use(function(req, res, next){ res.send('ok'); }); app.listen(3000);
node basic.js
運行程式,併在瀏覽器里訪問 http://127.0.0.1:3000 ,列印日誌如下
::1 - GET / HTTP/1.1 200 2 - 3.157 ms ::1 - GET / HTTP/1.1 304 - - 0.784 ms
morgan支持stream配置項,可以通過它來實現將日誌落地的效果,代碼如下:
var express = require('express'); var app = express(); var morgan = require('morgan'); var fs = require('fs'); var path = require('path'); var accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), {flags: 'a'}); app.use(morgan('short', {stream: accessLogStream})); app.use(function(req, res, next){ res.send('ok'); }); app.listen(3000);
morgan的API非常少,使用頻率最高的就是morgan()
,作用是返回一個express日誌中間件
morgan(format, options)
參數說明如下:
format:可選,morgan與定義了幾種日誌格式,每種格式都有對應的名稱,比如combined、short等,預設是default
options:可選,配置項,包含stream(常用)、skip、immediate
stream:日誌的輸出流配置,預設是process.stdout
skip:是否跳過日誌記錄
immediate:布爾值,預設是false。當為true時,一收到請求,就記錄日誌;如果為false,則在請求返回後,再記錄日誌
路由
【路由方法】
針對不同的請求,Express提供了use方法的一些別名,這些別名是和 HTTP 請求對應的路由方法: 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
app.all()
是一個特殊的路由方法,沒有任何 HTTP 方法與其對應,它的作用是對於一個路徑上的所有請求載入中間件
有些路由方法名不是合規的 JavaScript 變數名,此時使用括弧記法,比如 app['m-search']('/', function ...
var express = require("express"); var http = require("http"); var app = express(); app.all("*", function(request, response, next) { response.writeHead(200, { "Content-Type": "text/plain" }); next(); }); app.get("/", function(request, response) { response.end("Welcome to the homepage!"); }); app.get("/about", function(request, response) { response.end("Welcome to the about page!"); }); app.get("*", function(request, response) { response.end("404!"); }); http.createServer(app).listen(1337);
上面代碼的all方法表示,所有請求都必須通過該中間件,參數中的“*”表示對所有路徑有效。get方法則是只有GET動詞的HTTP請求通過該中間件,它的第一個參數是請求的路徑。由於get方法的回調函數沒有調用next方法,所以只要有一個中間件被調用了,後面的中間件就不會再被調用了
【路由路徑】
路由方法的第一個參數,都是請求的路徑,稱為路由路徑,它可以是字元串、字元串模式或者正則表達式
1、字元串匹配
// 匹配 /about 路徑的請求 app.get('/about', function (req, res) { res.send('about'); });
2、字元串模式匹配
// 匹配 acd 和 abcd app.get('/ab?cd', function(req, res) { res.send('ab?cd'); });
3、正則表達式匹配
// 匹配任何路徑中含有 a 的路徑: app.get(/a/, function(req, res) { res.send('/a/'); });
【路由句柄】
可以為請求處理提供多個回調函數,其行為類似中間件。唯一的區別是這些回調函數可能調用 next('route')
方法而略過其他路由回調函數。可以利用該機製為路由定義前提條件,如果在現有路徑上繼續執行沒有意義,則可將控制權交給剩下的路徑
路由句柄有多種形式,可以是一個函數、一個函數數組,或者是兩者混合
1、使用一個回調函數處理路由
app.get('/example/a', function (req, res) { res.send('Hello from A!'); });
2、使用多個回調函數處理路由
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!'); });
3、使用回調函數數組處理路由
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]);
4、混合使用函數和函數數組處理路由
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!'); });
【鏈式路由句柄】
可使用 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 4.0開始,路由器功能成了一個單獨的組件Express.Router
。它好像小型的express應用程式一樣,有自己的use、get、param和route方法
可使用 express.Router
類創建模塊化、可掛載的路由句柄。Router
實例是一個完整的中間件和路由系統,因此常稱其為一個 “mini-app”
【基本用法】
首先,Express.Router
是一個構造函數,調用後返回一個路由器實例。然後,使用該實例的HTTP動詞方法,為不同的訪問路徑,指定回調函數;最後,掛載到某個路徑
var express = require('express'); var router = express.Router(); router.get('/', function(req, res) { res.send('首頁'); }); router.get('/about', function(req, res) { res.send('關於'); }); app.use('/', router);
上面代碼先定義了兩個訪問路徑,然後將它們掛載到根目錄。如果最後一行改為app.use(‘/app’, router),則相當於為/app
和/app/about
這兩個路徑,指定了回調函數。
這種路由器可以自由掛載的做法,為程式帶來了更大的靈活性,既可以定義多個路由器實例,也可以為將同一個路由器實例掛載到多個路徑
【router.route方法】
router實例對象的route方法,可以接受訪問路徑作為參數
var express = require('express'); var router = express.Router(); router.route('/api') .post(function(req, res) { // ... }) .get(function(req, res) { Bear.find(function(err, bears) { if (err) res.send(err); res.json(bears); }); }); app.use('/', router);
【router中間件】
use方法為router對象指定中間件,在數據正式發給用戶之前,對數據進行處理。下麵是一個中間件的例子
router.use(function(req, res, next) { console.log(req.method, req.url); next(); });
上面代碼中,回調函數的next參數,表示接受其他中間件的調用。函數體中的next(),表示將數據傳遞給下一個中間件
[註意]中間件放置順序很重要,等同於執行順序。而且,中間件必須放在HTTP動詞方法之前,否則不會執行
【對路徑參數的處理】
router對象的param方法用於路徑參數的處理
router.param('name', function(req, res, next, name) { // 對name進行驗證或其他處理…… console.log(name); req.name = name; next(); }); router.get('/hello/:name', function(req, res) { res.send('hello ' + req.name + '!'); });
上面代碼中,get方法為訪問路徑指定了name參數,param方法則是對name參數進行處理
[註意]param方法必須放在HTTP動詞方法之前
【實例】
下麵的實常式序創建了一個路由模塊,並載入了一個中間件,定義了一些路由,並且將它們掛載至應用路徑上
在 app 目錄下創建名為 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
中間件
響應方法
response對象包含以下9個方法,response對象的方法向客戶端返迴響應,終結請求響應的迴圈。如果在路由句柄中一個方法也不調用,來自客戶端的請求會一直掛起
方法 描述
res.download() 提示下載文件。
res.end() 終結響應處理流程。
res.json() 發送一個 JSON 格式的響應。
res.jsonp() 發送一個支持 JSONP 的 JSON 格式的響應。
res.redirect() 重定向請求。
res.render() 渲染視圖模板。
res.send() 發送各種類型的響應。
res.sendFile() 以八位位元組流的形式發送文件。
res.sendStatus() 設置響應狀態代碼,並將其以字元串形式作為響應體的一部分發送。
1、response.download方法
//下載路徑為'/report-12345.pdf'的文件 res.download('/report-12345.pdf'); //下載路徑為'/report-12345.pdf'的文件,並將文件命名為 'report.pdf' res.download('/report-12345.pdf', 'report.pdf'); //下載路徑為'/report-12345.pdf'的文件,將文件命名為 'report.pdf',並且回調 res.download('/report-12345.pdf', 'report.pdf', function(err){ if (err) { } else { } });
2、response.end方法
//終結響應處理流程 res.end(); //設置響應碼為404,並終結響應處理流程 res.status(404).end();
3、response.json方法
res.json(null) res.json({ user: 'tobi' }) res.status(500).json({ error: 'message' })
4、response.jsonp方法
res.jsonp(null) res.jsonp({ user: 'tobi' }) res.status(500).jsonp({ error: 'message' })
5、response.redirect方法
res.redirect('/foo/bar'); res.redirect('http://example.com'); res.redirect(301, 'http://example.com'); res.redirect('../login');
6、response.render方法
res.render('index'); res.render('index', function(err, html) { res.send(html); }); res.render('user', { name: 'Tobi' }, function(err, html) { // ... });
7、response.send方法
res.send(new Buffer('whoop')); res.send({ some: 'json' }); res.send('<p>some html</p>'); res.status(404).send('Sorry, we cannot find that!'); res.status(500).send({ error: 'something blew up' });
8、response.sendFile方法
response.sendFile("/path/to/anime.mp4");
9、response.sendStatus方法
res.sendStatus(200); // 'OK' res.sendStatus(403); // 'Forbidden' res.sendStatus(404); // 'Not Found' res.sendStatus(500); // 'Internal Server Error'
請求方法
【req.params】
// GET /user/tj req.params.name // => "tj" // GET /file/javascripts/jquery.js req.params[0] // => "javascripts/jquery.js"
【req.query】
// GET /search?q=tobi+ferret req.query.q // => "tobi ferret" // GET /shoes?order=desc&shoe[color]=blue&shoe[type]=converse req.query.order // => "desc" req.query.shoe.color // => "blue" req.query.shoe.type // => "converse"
【req.body】
// POST user[name]=tobi&user[email][email protected] req.body.user.name // => "tobi" req.body.user.email // => "[email protected]" // POST { "name": "tobi" } req.body.name // => "tobi"
【req.param(name)】
// ?name=tobi req.param('name') // => "tobi" // POST name=tobi req.param('name') //