Express 学习笔记(2):路径参数(Route Parameter)

(注:部分示例摘自或修改自《Pro Node.js for Developers》)

Route Parameter

上次我们讲到了Express中的“路径”(Routes)。在Express中,我们可以通过调用get()、post()、delete()等函数来指定“当某个URL以某个方法被访问时,执行某个操作”。这类函数的第一个参数是个字符串,用来表示URL。第二个参数是个回调函数,表示当URL被请求时执行的操作。

这回我们就来说说这类函数的第一个参数——URL字符串。

在传统的网站架构中,URL地址几乎是固定不变的,变的是在访问URL过程中附带的一些参数,例如:

http://bbs.weiphone.com/forum.php?mod=viewthread&tid=771339&extra=page&page=2

它的URL实际上是http://bbs.weiphone.com/forum.php

而后面的“mod=viewthread&tid=771339&extra=page&page=2”实际上是一大堆附带的参数。

如果服务器端想要动态地响应用户的请求,那么在URL中附带一些附加信息(参数)是避免不了的问题。在传统架构中我们通过向URL塞入大量的难以阅读的键值对(Key-Value)来传递参数。但是在现在的架构中,我们通常将这些参数作为URL中的一部分进行传递,而服务器端在收到这些参数后再根据URL的结构进行处理。例如这样的URL:

http://www.mybooks.com/book/13235/chapter/12

http://www.mybooks.com/book/28754/chapter/2

我们将书的编号“13235”、“28754”和章节“12”、“2”作为URL中的一部分传递给服务器端。所以这个URL的“基本结构”形如:

http://www.mybooks.com/book/{book_id}/chapter/{chapter_number}。

其中{book_id}和{chapter_number}作为参数会被融入进URL。

再比如说,知乎网上的问题的URL大致都是这样的:

http://www.zhihu.com/question/22957469

http://www.zhihu.com/question/28329913

http://www.zhihu.com/question/42312312

http://www.zhihu.com/question/11231125

不难看出,这个URL的结构应该是:

http://www.zhihu.com/question/{question_number}

其中{question_number}将作为信息被包含到URL中

此时问题就出现了:如何将上面的参数在URL字符串中表示出来?如何在回调函数中获取到这个“URL中附带的信息”?Express中提供了很多种方式来实现我们的需求。

现在想象一下我们在设计一个电子商务网站,我们想要获取某个产品的信息,可以规划处这样一个URL:/products?product=sweater,但是有使用另一种风格定义的URL会更好看一些:/products/sweater。在Express中,我们可以通过定义“正则表达式”来定义一个URL和其中的参数。

例如:

var express = require("express");  
var http = require("http");  
var app = express();

app.get(/\/products\/([^\/]+)\/?$/,function(req, res, next){  
    res.send("Requested"+ req.params[0]);
});

http.createServer(app).listen(8000);  

上面get函数中的第一个参数就是一个“正则表达式”。所谓正则表达式,是一种规范化字符串的工具。使用正则表达式可以精确地将字符串限定在某个要求范围内。具体如何写正则表达式已经超出讲述的范围,请大家自行查阅。

但是正则表达式用起来是那么的麻烦,所以Express又提供了另一种方法来表示URL中的参数,例如:

var express = require("express");  
var http = require("http");  
var app = express();

app.get("/products/:productId",function(req, res, next){  
    res.send("Requested" + req.params.productId);
})

http.createServer(app).listen(8000);  

上面这个例子中的URL字符串更加易懂。不难发现,在productId之前有一个冒号,这个冒号就是指定“productId”是一个参数。而在req.params对象中Express会自动填充一个productId参数,其值就是在访问URL时附带的值。

但此时可能会遇到一个问题,productId应该是一个数字,但是现在的表示方法使得诸如 /product/a_product这样的URL也将会被处理,并且req.params.productId的值将会是“a_product”。如何能限制这个productId让它的值只能是数字?答案还是正则表达式。我们只需要在productId后面增加一个括号,在里面用正则表达式来表示出对这个参数的限制,例如(\d+)表示可以是至少一位的数字。但由于这个表示是在字符串中,所以我们需要再多加一个“\”来让后面的“\”转义:“(\d+)”。如此一来我们上面的例子就变成了:

var express = require("express");  
var http = require("http");  
var app = express();

app.get("/products/:productId(\\d+)",function(req, res, next){  
    res.send("Requested" + req.params.productId);
})

http.createServer(app).listen(8000);  

上面这种“现代的”URL设计方法是Restful API技术中的一部分,大家如果有兴趣可以去自行查阅一下。关于正则表达式,也希望大家能够通过查阅一些资料来学习。

Friskit

继续阅读此作者的更多文章