从零开始学习Express二 路由

路由是什么
以我自己的理解,通俗易懂的讲路由就是用户访问我们时候的一个入口。包括两部分,一个地址,一个动作。地址通常以uri形式出现,例如一个网址http://www.baidu.com,动作的话包括:get、post、put、delete等等,通常我们访问一个网站,就是get了一个网站地址。

明白了路由之后,我们就知道了其重要性,没有路由,用户也就无从访问我们的网站或者其他服务。下面,来看看express中如何定义路由。

 

上一篇我们讲了如何创建一个应用实例,如下:

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

接下来,我们就可以在应用上定义各种路由

定义一个根目录的GET请求:

app.get('/', function(req, res, next) {
    res.send("这是一个GET请求");
});

定义一个指向关于页面的GET请求:

app.get('/about', function(req, res, next) {
    res.send('这是关于页面');
});

定义了一个根目录的POST请求:

app.post('/', function(req, res, next) {
    res.json({
    msg: "这是一个POST请求"
    });
});

从上面的代码可以看出,首先我们用get或者post定义了路由的动作类型,然后通过'/'、'/about'指定了路由的路径,而后面的function则是我们对路由请求的处理。

这里的路径定义细分的话,可以分为3种:

1.纯字符串路径,明确指定请求路径

向上面的代码就是最纯粹的字符串类型,这里不再重复。

2.带有通配符的字符串路径

常用通配符:

?-0个或一个
+-1个或多个
*-1个或多个

app.get('/abcd?', function(req, res, next) {
    res.send(req.url);
});

上面的路由可以匹配路径/abcd和/abc

app.get('/abcd+', function(req, res, next) {
    res.send(req.url);
});

上面的路由可以匹配路径/abcd、/abcdd、/abcddd等。

3.正则表达式路径

首先我们要了解正则表达式,这是一种非常灵活的匹配方式,不熟悉的可以自行百度。

app.get(/\/baidu.*/, function(req, res, next) {
    res.send(req.url);
});

上面的路由可以匹配/baidu开始的任何路径,如/baidu、/baidu/about、/baidu123等等

app.get(/\/baidu[0-9]+$/, function(req, res, next) {
    res.send(req.url);
});

上面的路由可以匹配/baidu开始并且数字结束的任何路径,如/baidu1、/baidu123等等,但不匹配/baidu,如果希望匹配/baidu,需要路径定义修改为/\/baidu[0-9]*$/。

了解了路径定义之后,我们就可以根据业务需求和系统结构来定义用户访问的入口路径,但这只是入口,当用户根据我们提供的入口发起请求之后,我们对用户的请求进行处理并且做出合理的回应才是重点,而这就是上面所说的funciton的工作,我们把它叫做callback(回调,即用户发起请求后,系统会调用这个过程进行处理)。

一个callback就是一个function,这个function至少有两个参数,req(请求对象)、res(响应对象)

req对象就是用户发起请求时所构建的对象,里面存储有用户请求的参数,常用的有两个:

req.query.参数名称 GET请求时获取请求参数的方法,如req.query.name
req.body.参数名称 POST请求时获取请求参数的方法,如req.body.password

 res对象是我们反馈给用户的对象,用于将我们的处理结果发送给用户或请求端,常用的方法有:

res.download() 提示下载文件。
res.end() 终结响应处理流程。
res.json() 发送一个 JSON 格式的响应。
res.jsonp() 发送一个支持 JSONP 的 JSON 格式的响应。
res.redirect() 重定向请求。
res.render() 渲染视图模板。
res.send() 发送各种类型的响应。
res.sendFile 以八位字节流的形式发送文件。
res.sendStatus() 设置响应状态代码,并将其以字符串形式作为响应体的一部分发送。

req和res更加具体的使用方法请自行百度,这里只从大的方面进行学习和讲解,不涉及过于具体的问题。

 

对于一个路由,可以定义多个callback对请求进行处理,系统会按照次序执行。

app.get('/test', function(req, res, next) {
    console.log("第一个callback");
    next();
}, function(req, res) {
    console.log("第二个callback");
    res.send("执行结束。");
});

请求/test后,控制台输出如下:

 

这里我们发现第一个callback有3个参数,多了一个next,这个很重要。

next负责控制权的传递,在每一个callback的最后,我们都会调用next();这样所有callback都会依次执行。

如果某个callback没有调用next();那后面的callback将没有机会被调用;并且如果前面的callback没有任何响应请求的动作,客户请求将被挂起。

如果根据业务需求,当执行到某个callback时,要跳过剩余的callback处理,可以调用next('route');进入下一个匹配的路由进行处理,如果有的话。

 

多个callback处理,除了上面的写法之外,还可以使用函数数组的方式,如下:

var a = function(req, res, next) {
    console.log("第一个callback");
    next();
}

var b = function(req, res, next) {
    console.log("第二个callback");
    next();
}

var c = function(req, res, next) {
    res.send("hello world.");
};

app.get('/test', [a, b, c]);

写法不同,执行结果一致,大家可以根据各自风格自行选择。
除此之外,还可以混合使用,如:

app.get('/test', [a, b], function(req, res, next) {
    res.send('hello world.');
});

 至此,我们已经了解了使用express如何定义一个路由,并且如何控制处理分配到这个路由的请求。

接下来,再补充两种定义路由的方法。

上面的定义方法,我称之为以方法为导向,如get或者post等,先定义好一个方法,再后续定义路径和处理方法。

第二种路由定义方法:以路径为导向

app.router('/test').get(function(req, res, next() {
    res.send("/test 请求方法是GET");
}).post(function(req, res, next) {
    res.send("/test 请求方法是POST");
});

这种方法,首先确定了请求路径,然后再定义不同的请求方法,以及各自的回调处理函数。

第三种路由定义方法:Router模块定义

当我们系统功能比较复杂,模块比较多;如果将路由全部定义在一个文件里,太混乱,不容易维护和管理,因此我们可以使用Router模块分别定义,然后再挂载到app上。

首先新建一个blog.js文件,内容如下:

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

router.get('/', function(req, res, next) {
    res.send('这是一个模块定义');
});

router.get('/list', function(req, res, next) {
    res.send('这是一个列表返回');
});

router.get('/list/:id', function(req, res, next) {
    var id = req.params.id;    //通过req.params.id可以获取路径定义中的:id的值,当然也可以定义成其他的名字。
    res.send('这是一个详情');
});

//最后要导出这个定义
module.exports = router;

这样我们就定义了一个模块的路由,包括访问路径以及处理方法和响应信息。
此时,路由还不能访问,接下来我们将它挂载到app上,使其能够被我们访问到。

回到app.js中,然后通过如下方法进行挂载:

//首先引用我们的模块定义,需要指向合适的路径,如果和app.js是同一目录的话,直接文件名即可,不需要后缀。
var blog = require('blog');

//进行挂载
app.use('/blog', blog);

到这里,我们的blog模块就真正挂载到了app上,启动我们的应用,就可以通过http://localhost:8080/blog、http://localhost:8080/blog/list、http://localhost:8080/blog/list/123路径进行访问了。

关于路由的讲解就到这里,内容比较多,但其实都比较简单,就是对路径、动作、请求处理过程的一个定义,本人是边学边记录,可能有些地方理解的不是很到位,出现错误的地方请大家指正,共同学习进步。

posted @ 2017-09-27 16:40  bcbr_wang  阅读(275)  评论(0编辑  收藏  举报