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