express目前是最流行的基於Node.js的web開發框架,express框架創建在內置的http模塊上,javascript
var http = require('http') var app = http.createServer(function(req,res){ res.writeHead(200,{"Content-type":"text/plain"}); res.end('hello world') }) app.listen(3000,'lcoalhost')
上面代碼的關鍵是使用createServer
方法,生成一個HTTP的服務器實例。該方法接受一個回調函數,回調函數的參數分別表明HTTP請求和HTTP迴應的request
和response
對象html
Experss框架的核心是對http模塊的再包裝,java
var express = require('express') var port = process.env.PORT || 3000 var app = express() app.get('/',fcuntion(req,res){ res.send('hello world') }) app.listen(port)
比較http.createServer()
方法建立一個app實例和Express的構造方法,生成一個Express實例,二者的回調函數都是相同的。Express框架等於在http模塊之上,加了一箇中間層node
Express是一個自身功能極簡單,徹底由路由
和中間件
構成的web開發框架,從本質上說,一個Express應用是在調用各類中間件web
中間件(middleware)
是一個函數,他能夠訪問請求對象(request object(req)),響應對象(response object(res))和web應用中處於請求-響應循環express
Express能夠使用以下幾種中間件:npm
- 應用級中間件 - 路由級中間件 - 錯誤處理中間件 - 內置中間件 - 第三方中間件
應用級中間鍵綁定到app對象
使用app.use
和app.METHOD()-須要處理http請求的方法,例如GET、PUT、POST
服務器
var app = express() // 沒有掛載路徑的中間件,應用中的每一個請求都會執行該中間件 app.use((req,res,next) => { console.log('Time',Dtae.now()); next(); // 傳遞request對象給下一個中間件 }) // 掛載至/user/:id的中間件,任何執行/user/:id的請求都會執行它 app.use('/use/:id',(req,res,next) => { console.log('Request Type',req.method); next(); }) // 路由和句柄函數(中間件系統),處理指向/user/:id的GET請求 app.get('/user/:id',(req,res,next)=>{ console.log('USER'); })
若是咱們想要處理掛在至/user/:id
的中間件的GET請求,咱們須要使用next()
將request
對象傳遞給下一個中間件cookie
否者:
app
得不到下一個中間件處理的它,一直在等待...
最終會拋出localhost未發送任何數據的錯誤
如何你不想要終止請求-響應循環
,老是記得經過next()
傳遞request對象
若是你想要在中間件棧中跳過剩餘中間件,調用next('route')方法將控制權交給下一個路由
app.get('/user/:id',(req,res,next)=>{ if(req.params.id==0) next('route') else next() },(req,res,next)=>{ // 渲染常規頁面 res.render('regular') }) // 處理/user/:id,渲染一個id爲0的特殊頁面 app.get('/user/:id',(req,res,next)=>{ res.render('special') })
路由級中間件和應用級中間件相似,只不過是它綁定對象爲express.Router()
var router = express.Router()
路由級使用router.use()
或router.VERB()
加載
舉個栗子
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',(req,res,next)=>{ console.log('Request URL',req.originalUrl) next() },(req,res,next)=>{ console.log('Request Type',req.method) next() }) // 一箇中間件棧,處理指向/user/:id的GET請求 router.get('/user/:id',(req,res,next)=>{ if(req.params.id == 0) next('router') else next() },(req,res,next)=>{ res.render('regular') }) // 處理/user/:id,渲染一個特殊頁面 router.get('user/:id',(req,res,next)=>{ console.log(req.params.id) res.render('special') }) // 將路由掛載至應用 app.use('/',router)
錯誤處理中間件有四個參數,定義錯誤處理中間件必須使用這四個參數。即便不須要next對象,也必須在參數中聲明它,否者中間件會識別爲一個常規中間件,不能處理錯誤
舉個栗子:
app.use((err,req,res,next)=>{ console.error(err.stack) res.status(500).send('Something broke') })
中間件返回的響應是隨意的,能夠響應一個 HTML 錯誤頁面、一句簡單的話、一個 JSON 字符串,或者其餘任何您想要的東西。
因此你可能想要像處理常規中間件那樣,定義多個錯誤處理中間件
,好比您想爲使用 XHR 的請求定義一個,還想爲沒有使用的定義一個,那麼:
app.use(logErrors) app.use(clientErrorHandler) app.use(errorHandler)
logErrors
將請求和錯誤信息寫入標準錯誤輸出、日誌或者相似服務
function logErrors(err,req,res,next){ console.error(err.stack) next(err) }
clientErrorHandler
定義以下(這裏將錯誤直接傳給了next)
function clientErrorHandler(err,req,res,next){ if(req.xhr){ res.status(500).send({error:'Something blew up!'}) }else{ next(err) } }
errorHandler
捕獲全部錯誤
function errorHandler(err,req,res,next){ res.status(500) res.render('error',{error:err}) }
從版本4.x開始,Express再也不依賴Content
,除了 express.static
, Express 之前內置的中間件如今已經所有單獨做爲模塊安裝使用
express.static
是 Express 惟一內置的中間件。
它基於 serve-static
,負責在 Express 應用中提託管靜態資源。
可選options
參數擁有以下屬性
屬性 | 描述 | 類型 | 缺省值 |
---|---|---|---|
dotfiles | 是否對外輸出文件名以點(.)開頭的文件。可選值爲 「allow」、「deny」 和 「ignore」 | String | "ignore" |
etag | 是否啓用etag生成 | Boolean | true |
extensions | 設置文件擴展名備份選項 | Array | [ ] |
index | 發送目錄索引文件,設置爲 false 禁用目錄索引。 | mixed | "index.html" |
lastModified | 設置 Last-Modified 頭爲文件在操做系統上的最後修改日期 | Boolean | true |
maxAge | 毫秒或者其字符串格式設置 Cache-Control 頭的 max-age 屬性 | Number | 0 |
redirect | 當路徑爲目錄時,重定向至"/" | Boolean | true |
setHeaders | 設置HTTP頭以提供文件的函數 | Function |
下面的栗子使用了 express.static
中間件,其中的 options
對象通過了精心的設計。
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));
咱們老是須要使用express.static
指定多個靜態資源文件,好比:
app.use(express.static('public')) app.use(express.static('files'))
經過使用第三方中間件從而爲Express應用增長更多的功能
安裝所需功能的node模塊,並在應用中加載,能夠在應用級中加載,也能夠在路由級中加載
舉個栗子
$ npm install cookie-parser
var express = require('express') var app = express() var cookieParser = require('cookie-parser') // 加載用於解析cookie的中間件 app.use(cookieParser())
參考資料