1. 程式人生 > >Node.js輕量級Web框架Express4.x使用指南

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就會把必要的資料夾以及程式碼快速生成了