欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

nodejs開(kāi)發(fā)——express路由與中間件

 更新時(shí)間:2017年03月24日 14:40:07   作者:前端愛(ài)好者  
本篇文章主要介紹了nodejs開(kāi)發(fā)——express路由與中間件 ,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

路由

通常HTTP URL的格式是這樣的:

http://host[:port][path]

http表示協(xié)議。

host表示主機(jī)。

port為端口,可選字段,不提供時(shí)默認(rèn)為80。

path指定請(qǐng)求資源的URI(Uniform Resource Identifier,統(tǒng)一資源定位符),如果URL中沒(méi)有給出path,一般會(huì)默認(rèn)成“/”(通常由瀏覽器或其它HTTP客戶(hù)端完成補(bǔ)充上)。

所謂路由,就是如何處理HTTP請(qǐng)求中的路徑部分。比如“http://xxx.com/users/profile”這個(gè)URL,路由將決定怎么處理/users/profile這個(gè)路徑。

來(lái)回顧我們?cè)贜ode.js開(kāi)發(fā)入門(mén)——Express安裝與使用中提供的express版本的HelloWorld代碼:

var express = require('express');
var app = express();

app.get('/', function (req, res) {
 res.send('Hello World!');
});

app.listen(8000, function () {
 console.log('Hello World is listening at port 8000');
});

上面代碼里的app.get()調(diào)用,實(shí)際上就為我們的網(wǎng)站添加了一條路由,指定“/”這個(gè)路徑由get的第二個(gè)參數(shù)所代表的函數(shù)來(lái)處理。

express對(duì)象可以針對(duì)常見(jiàn)的HTTP方法指定路由,使用下面的方法:

app.METHOD(path, callback [, callback ...])

路由路徑

使用字符串的路由路徑示例:

// 匹配根路徑的請(qǐng)求

app.get('/', function (req, res) {

 res.send('root');

});

// 匹配 /about 路徑的請(qǐng)求

app.get('/about', function (req, res) {

 res.send('about');

});

// 匹配 /random.text 路徑的請(qǐng)求

app.get('/random.text', function (req, res) {

 res.send('random.text');

});

使用字符串模式的路由路徑示例:

// 匹配 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');

});

字符 ?、+、* 和 () 是正則表達(dá)式的子集,- 和 . 在基于字符串的路徑中按照字面值解釋。

使用正則表達(dá)式的路由路徑示例:

// 匹配任何路徑中含有 a 的路徑:

app.get(/a/, function(req, res) {

 res.send('/a/');

});

// 匹配 butterfly、dragonfly,不匹配 butterflyman、dragonfly man等

app.get(/.*fly$/, function(req, res) {

 res.send('/.*fly$/');

});

路由句柄

可以為請(qǐng)求處理提供多個(gè)回調(diào)函數(shù),其行為類(lèi)似 中間件。唯一的區(qū)別是這些回調(diào)函數(shù)有可能調(diào)用 next('route') 方法而略過(guò)其他路由回調(diào)函數(shù)??梢岳迷摍C(jī)制為路由定義前提條件,如果在現(xiàn)有路徑上繼續(xù)執(zhí)行沒(méi)有意義,則可將控制權(quán)交給剩下的路徑。

路由句柄有多種形式,可以是一個(gè)函數(shù)、一個(gè)函數(shù)數(shù)組,或者是兩者混合,如下所示.

使用一個(gè)回調(diào)函數(shù)處理路由:

app.get('/example/a', function (req, res) {

 res.send('Hello from A!');

});

使用多個(gè)回調(diào)函數(shù)處理路由(記得指定 next 對(duì)象):

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!');

});

使用回調(diào)函數(shù)數(shù)組處理路由:

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]);

混合使用函數(shù)和函數(shù)數(shù)組處理路由:

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!');

METHOD可以是GET、POST等HTTP方法的小寫(xiě),例如app.get,app.post。path部分呢,既可以是字符串字面量,也可以是正則表達(dá)式。最簡(jiǎn)單的例子,把前面代碼里的app.get()調(diào)用的一個(gè)參數(shù)'/'修改為'*',含義就不一樣。改動(dòng)之前,只有訪(fǎng)問(wèn)“http://localhost:8000”或“http://localhost:8000/”這種形式的訪(fǎng)問(wèn)才會(huì)返回“Hello World!”,而改之后呢,像“http://localhost:8000/xxx/yyyy.zz”這種訪(fǎng)問(wèn)也會(huì)返回“Hello World!”。

使用express構(gòu)建Web服務(wù)器時(shí),很重要的一部分工作就是決定怎么響應(yīng)針對(duì)某個(gè)路徑的請(qǐng)求,也即路由處理。

最直接的路由配置方法,就是調(diào)用app.get()、app.post()一條一條的配置,不過(guò)對(duì)于需要處理大量路由的網(wǎng)站來(lái)講,這會(huì)搞出人命來(lái)的。所以呢,我們實(shí)際開(kāi)發(fā)中需要結(jié)合路由參數(shù)(query string、正則表達(dá)式、自定義的參數(shù)、post參數(shù))來(lái)減小工作量提高可維護(hù)性。更詳細(xì)的信息,參考http://expressjs.com/guide/routing.html。

中間件

Express里有個(gè)中間件(middleware)的概念。所謂中間件,就是在收到請(qǐng)求后和發(fā)送響應(yīng)之前這個(gè)階段執(zhí)行的一些函數(shù)。

要在一條路由的處理鏈上插入中間件,可以使用express對(duì)象的use方法。該方法原型如下:

app.use([path,] function [, function...])

當(dāng)app.use沒(méi)有提供path參數(shù)時(shí),路徑默認(rèn)為“/”。當(dāng)你為某個(gè)路徑安裝了中間件,則當(dāng)以該路徑為基礎(chǔ)的路徑被訪(fǎng)問(wèn)時(shí),都會(huì)應(yīng)用該中間件。比如你為“/abcd”設(shè)置了中間件,那么“/abcd/xxx”被訪(fǎng)問(wèn)時(shí)也會(huì)應(yīng)用該中間件。

中間件函數(shù)的原型如下:

function (req, res, next)

第一個(gè)參數(shù)是Request對(duì)象req。第二個(gè)參數(shù)是Response對(duì)象res。第三個(gè)則是用來(lái)驅(qū)動(dòng)中間件調(diào)用鏈的函數(shù)next,如果你想讓后面的中間件繼續(xù)處理請(qǐng)求,就需要調(diào)用next方法。

給某個(gè)路徑應(yīng)用中間件函數(shù)的典型調(diào)用是這樣的:

app.use('/abcd', function (req, res, next) {
 console.log(req.baseUrl);
 next();
})

app.static中間件

Express提供了一個(gè)static中間件,可以用來(lái)處理網(wǎng)站里的靜態(tài)文件的GET請(qǐng)求,可以通過(guò)express.static訪(fǎng)問(wèn)。

express.static的用法如下:

express.static(root, [options])

第一個(gè)參數(shù)root,是要處理的靜態(tài)資源的根目錄,可以是絕對(duì)路徑,也可以是相對(duì)路徑。第二個(gè)可選參數(shù)用來(lái)指定一些選項(xiàng),比如maxAge、lastModified等,更多選項(xiàng)的介紹看這里:http://expressjs.com/guide/using-middleware.html#middleware.built-in。

一個(gè)典型的express.static應(yīng)用如下:

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));

上面這段代碼將當(dāng)前路徑下的public目錄作為靜態(tài)文件,并且為Cache-Control頭部的max-age選項(xiàng)為1天。還有其它一些屬性,請(qǐng)對(duì)照express.static的文檔來(lái)理解。

使用express創(chuàng)建的HelloExpress項(xiàng)目的app.js文件里有這樣一行代碼:

app.use(express.static(path.join(__dirname, 'public')));

這行代碼將HelloExpress目錄下的public目錄作為靜態(tài)文件交給static中間件來(lái)處理,對(duì)應(yīng)的HTTP URI為“/”。path是一個(gè)Node.js模塊,__dirname是Node.js的全局變量,指向當(dāng)前運(yùn)行的js腳本所在的目錄。path.join()則用來(lái)拼接目錄。

有了上面的代碼,你就可以在瀏覽器里訪(fǎng)問(wèn)“http://localhost:3000/stylesheets/style.css”。我們做一點(diǎn)改動(dòng),把上面的代碼修改成下面這樣:

app.use('/static', express.static(path.join(__dirname, 'public')));

上面的代碼呢,針對(duì)/static路徑使用static中間件處理public目錄。這時(shí)你再用瀏覽器訪(fǎng)問(wèn)“http://localhost:3000/stylesheets/”就會(huì)看到一個(gè)404頁(yè)面,將地址換成“http://localhost:3000/static/stylesheets/style.css”就可以了。

Router

Express還提供了一個(gè)叫做Router的對(duì)象,行為很像中間件,你可以把Router直接傳遞給app.use,像使用中間件那樣使用Router。另外你還可以使用router來(lái)處理針對(duì)GET、POST等的路由,也可以用它來(lái)添加中間件,總之你可以將Router看作一個(gè)微縮版的app。

下面的代碼創(chuàng)建一個(gè)Router實(shí)例:

var router = express.Router([options]);

然后你就可以像使用app一樣使用router:

// invoked for any requests passed to this router
router.use(function(req, res, next) {
 // .. some logic here .. like any other middleware
 next();
});

// will handle any request that ends in /events
// depends on where the router is "use()'d"
router.get('/events', function(req, res, next) {
 // ..
});

定義了router后,也可以將其作為中間件傳遞給app.use:

app.use('/events', router);

上面這種用法,會(huì)針對(duì)URL中的“/events”路徑應(yīng)用router,你在router對(duì)象上配置的各種路由策略和中間件,都會(huì)被在合適的時(shí)候應(yīng)用。

路由模塊

express工具創(chuàng)建的應(yīng)用,有一個(gè)routes目錄,下面保存了應(yīng)用到網(wǎng)站的Router模塊,index.js和user.js。這兩個(gè)模塊基本一樣,我們研究一下index.js。

下面是index.js的內(nèi)容:

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
 res.render('index', { title: 'Express' });
});

module.exports = router;

index.js創(chuàng)建了一個(gè)Router實(shí)例,然后調(diào)用router.get為“/”路徑應(yīng)用了路由函數(shù)。最后呢使用module.exports將Router對(duì)象導(dǎo)出。

下面是app.js里引用到index.js的代碼:

var routes = require('./routes/index');
...
app.use('/', routes);

第一處,require(‘./routes/index')將其作為模塊使用,這行代碼導(dǎo)入了index.js,并且將index.js導(dǎo)出的router對(duì)象保存在變量routes里以供后續(xù)使用。注意,上面代碼里的routes就是index.js里的router。

第二處代碼,把routes作為一個(gè)中間件,掛載到了“/”路徑上。

模塊

前面分析index.js時(shí)看到了module.exports的用法。module.exports用來(lái)導(dǎo)出一個(gè)Node.js模塊內(nèi)的對(duì)象,調(diào)用者使用require加載模塊時(shí),就會(huì)獲得導(dǎo)出的對(duì)象的實(shí)例。

我們的index.js導(dǎo)出了Router對(duì)象。app.js使用require(‘./routes/index')獲取了一個(gè)Router實(shí)例。

module.exports還有一個(gè)輔助用法,即直接使用exports來(lái)導(dǎo)出。

exports.signup = function(req, res){
 //some code
}

exports.login = function(req, res){
 //some code
}

上面的代碼(假定在users.js文件里)直接使用exports來(lái)導(dǎo)出。當(dāng)使用exports來(lái)導(dǎo)出時(shí),你設(shè)置給exports的屬性和方法,實(shí)際上都是module.exports的。這個(gè)模塊最終導(dǎo)出的是module.exports對(duì)象,你使用類(lèi)似“exports.signup”這種形式設(shè)置的方法或?qū)傩?,調(diào)用方在require后都可以直接使用。

使用users模塊的代碼可能是這樣的:

var express = require('express');
var app = express();
...
var users = require('./routes/users');
app.post('/signup', users.signup);
app.post('/login', users.login);
...

1.  什么是router路徑,什么是middleware?

我們輸入www.baidu.com 來(lái)訪(fǎng)問(wèn)百度的主頁(yè),瀏覽器會(huì)自動(dòng)轉(zhuǎn)換為 http://www.baidu.com:80/(省略一些參數(shù))。 http://代表我們同服務(wù)器連接使用的是http協(xié)議,www.baidu.com 代表的是服務(wù)器的主機(jī)地址,會(huì)被我們的pc通過(guò)DNS解析為IP地址。80是默認(rèn)的應(yīng)用層端口。/ 即為我們?cè)L問(wèn)的服務(wù)器(www.baidu.com)的路徑,服務(wù)器要對(duì)我們?cè)L問(wèn)的這個(gè)路徑做出響應(yīng),采取一定的動(dòng)作。我們可以把這一過(guò)程看做一個(gè)路由。

 訪(fǎng)問(wèn)的路徑‘/'即為router的路徑,服務(wù)器采取的動(dòng)作即為middleware,即為一個(gè)個(gè)特殊的函數(shù)。

2. router路徑

www.baidu.com/test: 路徑為 /test

www.baidu.com/test?name=1&number=2: 路徑同樣為/test, ?后面會(huì)被服務(wù)器理解傳給路徑的參數(shù)。

3. Middleware

An Express application is essentially a stack of middleware which are executed serially.(express應(yīng)用其實(shí)就是由一系列順序執(zhí)行的Middleware組成。)

A middleware is a function with access to the request object (req), the response object (res), and the next middleware in line in the request-response cycle of an Express application. It is commonly denoted by a variable named next. Each middleware has the capacity to execute any code, make changes to the request and the reponse object, end the request-response cycle, and call the next middleware in the stack. Since middleware are execute serially, their order of inclusion is important.(中間件其實(shí)就是一個(gè)訪(fǎng)問(wèn)express應(yīng)用串入的req,res,nex參數(shù)的函數(shù),這個(gè)函數(shù)可以訪(fǎng)問(wèn)任何通過(guò)req,res傳入的資源。)

If the current middleware is not ending the request-response cycle, it is important to call next() to pass on the control to the next middleware, else the request will be left hanging.(如果當(dāng)前中間件沒(méi)有完成對(duì)網(wǎng)頁(yè)的res響應(yīng) ,還可以通過(guò)next把router 留給下一個(gè)middleware繼續(xù)執(zhí)行)

With an optional mount path, middleware can be loaded at the application level or at the router level. Also, a series of middleware functions can be loaded together, creating a sub-stack of middleware system at a mount point.

路由的產(chǎn)生是通過(guò)HTTP的各種方法(GET, POST)產(chǎn)生的,Middleware可以跟router路徑跟特定的HTTP方法綁定,也可以跟所有的方法綁定。

3.1 通過(guò)express應(yīng)用的use(all),把Middleware同router路徑上的所有HTTP方法綁定:

 app.use(function (req, res, next) {
  console.log('Time: %d', Date.now());
  next();
 })

3.2 通過(guò)express應(yīng)用的http.verb,把Middleware同router路徑上的特定的HTTP方法綁定:

app.get('/', function(req, res){
 res.send('hello world');
});


app.post('/', function(req, res){
 res.send('hello world');
});

4.  Express的Router對(duì)象

當(dāng)express實(shí)例的路由越來(lái)越多的時(shí)候,最好把路由分類(lèi)獨(dú)立出去,express的實(shí)例(app) 能更好的處理其他邏輯流程。Express的Router對(duì)象是一個(gè)簡(jiǎn)化的 app實(shí)例,只具有路由相關(guān)的功能,包括use, http verbs等等。最后這個(gè)Router再通過(guò)app的use掛載到app的相關(guān)路徑下。

 var express = require('express');
var app = express();
var router = express.Router();

// simple logger for this router's requests
// all requests to this router will first hit this middleware
router.use(function(req, res, next) {
 console.log('%s %s %s', req.method, req.url, req.path);
 next();
});

// this will only be invoked if the path ends in /bar
router.use('/bar', function(req, res, next) {
 // ... maybe some additional /bar logging ...
 next();
});

// always invoked
router.use(function(req, res, next) {
 res.send('Hello World');
});

app.use('/foo', router);

app.listen(3000);

router的路由必須通過(guò)app.use和app.verbs 掛載到app上才能被響應(yīng)。所以上述代碼,只有在app捕捉到 /foo路徑上的路由時(shí),才能router中定義的路由,雖然router中有針對(duì) '/' 的路由,但是被app中的路由給覆蓋了。

附:app.verbs和app.use的路由路徑區(qū)別:

先看一段測(cè)試代碼:

var express = require('express');

var app = express();
var router = express.Router();

app.get('/', function(req, res){
   console.log('test1');
});

app.use('/', function(req, res){
   console.log('test2');
});

router.get('/', function(req, res){
   console.log('test3');
});

app.listen(4000);

輸入url: localhost:4000

輸出結(jié)果:test1 

輸入url: localhost:4000/hello

輸出結(jié)果:test2

結(jié)論:app.get掛載‘/'的路由只響應(yīng)跟'/'精確匹配的GET請(qǐng)求。 而app.use掛載的'/'的路由響應(yīng)所有以'/' 為起始路由的路由,且不限制HTTP訪(fǎng)問(wèn)的方法。以下說(shuō)明:Mounting a middleware at a path will cause the middleware function to be executed whenever the base of the requested path matches the path.

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 一文詳解Node中module.exports和exports區(qū)別

    一文詳解Node中module.exports和exports區(qū)別

    這篇文章主要介紹了一文詳解Node中module.exports和exports區(qū)別
    2023-03-03
  • 輕松創(chuàng)建nodejs服務(wù)器(2):nodejs服務(wù)器的構(gòu)成分析

    輕松創(chuàng)建nodejs服務(wù)器(2):nodejs服務(wù)器的構(gòu)成分析

    這篇文章主要介紹了輕松創(chuàng)建nodejs服務(wù)器(2):nodejs服務(wù)器的構(gòu)成分析,本文是對(duì)第一節(jié)中簡(jiǎn)單服務(wù)器的代碼進(jìn)行分析總結(jié),需要的朋友可以參考下
    2014-12-12
  • Node.js實(shí)現(xiàn)解析post請(qǐng)求的方法詳解

    Node.js實(shí)現(xiàn)解析post請(qǐng)求的方法詳解

    這篇文章主要為大家詳細(xì)介紹了Node.js實(shí)現(xiàn)解析post請(qǐng)求方法的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,有需要的小伙伴可以了解下
    2024-04-04
  • 解析NodeJS異步I/O的實(shí)現(xiàn)

    解析NodeJS異步I/O的實(shí)現(xiàn)

    本篇文章主要介紹了解析NodeJS異步I/O的實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-04-04
  • nodejs Assert中equal(),strictEqual(),deepEqual(),strictDeepEqual()比較

    nodejs Assert中equal(),strictEqual(),deepEqual(),strictDeepEq

    這篇文章主要介紹了node項(xiàng)目中遇到使用斷言測(cè)試程序,看了下nodejs的api之后,對(duì)nodejs中assert斷言的幾個(gè)方法做個(gè)簡(jiǎn)單的記錄,需要的朋友可以參考下
    2017-09-09
  • node.js文件上傳重命名以及移動(dòng)位置的示例代碼

    node.js文件上傳重命名以及移動(dòng)位置的示例代碼

    本篇文章主要介紹了node.js文件上傳重命名以及移動(dòng)位置的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • node下使用UglifyJS壓縮合并JS文件的方法

    node下使用UglifyJS壓縮合并JS文件的方法

    下面小編就為大家分享一篇node下使用UglifyJS壓縮合并JS文件的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • node.js中的http.response.addTrailers方法使用說(shuō)明

    node.js中的http.response.addTrailers方法使用說(shuō)明

    這篇文章主要介紹了node.js中的http.response.addTrailers方法使用說(shuō)明,本文介紹了http.response.addTrailers的方法說(shuō)明、語(yǔ)法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • Nodejs 微信小程序消息推送的實(shí)現(xiàn)

    Nodejs 微信小程序消息推送的實(shí)現(xiàn)

    這篇文章主要介紹了Nodejs 微信小程序消息推送的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Node的stream數(shù)據(jù)流你了解嗎

    Node的stream數(shù)據(jù)流你了解嗎

    這篇文章主要為大家詳細(xì)介紹了Node的stream數(shù)據(jù)流,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02

最新評(píng)論