学习使用ExpressJS 4.0中的新Router
概述
ExpressJS 4.0中提出了新的路由Router
。Router好比是一个“迷你版”的express应用,它没有引入views
或者settings
,但是提供了路由应有的API,.use
,.get
,.param
和route
。
示例应用
让我们创建一个express应用,仅仅有少量routes和功能:
- 基础路由:
Home
,About
- 一个把request请求打印到console的路由中间件
- 一个带参数的路由
- 一个校验特殊参数的路由中间件
- 一个用于登录的路由,响应对与路径
/login
的GET和POST请求 - 校验功能:校验传递给某一个路由的参数
应用文件架构
我们只需要两个文件:
- package.json // 构建node应用所需要的插件 - server.js // 构建示例应用的启动文件
我们会把路由代码写如server.js
文件。将来为了让示例应用模块化,我们会把这些路由代码分别写入不同的文件,甚至可以为网站的不同组成部分单独定义不同的路由文件。
创建Node应用
创建node应用,我们需要编写package.json
文件去定义node应用依赖的插件。
{ "name": "express-router-experiments", "main": "server.js", "dependencies": { "express": "~4.0.0" } }
下面继续安装依赖:
$ npm install
现在我们安装了Express,让我们继续编写server.js
去处理路由。
创建server
我们在package.json
中指定了main
属性值为server.js
,因此Express会使用server.js
作为应用的入口文件。
// server.js // 基础设置 // ============================================== var express = require('express'); var app = express(); var port = process.env.PORT || 8080; // 路由 // ============================================== // 示例路由 app.get('/sample', function(req, res) { res.send('this is a sample!'); }); // 我们会在这里编写自己的路由 // 启动server // ============================================== app.listen(port); console.log('Magic happens on port ' + port);
现在我们可以使用命令node server.js
启动server。我们使用app.get
创建了一个Express 3时代的路由,如果此时打开浏览器访问http://localhost:8080/sample
,我们就能看到这样下面的文字:this is a sample!
。
基本用法 express.Router()
下面我们一起编写Node应用前端路由的例子,包括Home页面和About页面。
// server.js ... // 获取router实例 var router = express.Router(); // home页面路由(http://localhost:8080) router.get('/', function(req, res) { res.send('im the home page!'); }); // about页面路由(http://localhost:8080/about) router.get('/about', function(req, res) { res.send('im the about page!'); }); // 把定义好的路由集成到Node应用中 app.use('/', router); ...
我们前面的代码使用express.Router()生成一个路由实例,并定义路由规则,最后把这个路由实例集成到应用中。现在我们可以通过http://localhost:8080
访问Home页面,通过http://localhost:8080/about
访问about页面。
请注意:我们可以改变前面定义的路由中默认的根路径('/')。如果我们把app.use('/', router)
改为app.use('/app', router)
,那么home页面的访问地址变为http://localhost:8080/app
,about页面的访问地址变为http://localhost:8080/app/about
。
这是一个非常有用的功能,我们可以利用它创建多个路由实例express.Router()
并把这些实例都集成到Node应用中。例如,可以在Node应用中针对不同功能需求创建不同的路由:一个基础路由,一个用于权限校验的路由和其他API路由。如此一来,Node应用变得更加模块化更容易扩展。
创建路由中间件Router.use()
路由中间件实际是一种允许一个request请求被处理之前进行某些操作的机制。例如,在把一个request请求的响应数据返回给用户之前,我们可以检查用户是否有权限,可以记录日志等等。
下面我们实现一个打印日志的中间件,每次有一个request请求,我们就在console打印一条信息。
// server.js ... // 获取router实例 var router = express.Router(); // 路由中间件:每当有一个request请求都会执行 router.use(function(req, res, next) { // 打印request的method和url console.log(req.method, req.url); // 继续处理request请求,寻找匹配的路由 next(); }); // home页面路由 (http://localhost:8080) router.get('/', function(req, res) { res.send('im the home page!'); }); // about页面路由 (http://localhost:8080/about) router.get('/about', function(req, res) { res.send('im the about page!'); }); // 把定义好的路由集成到Node应用中 app.use('/app', router); ...
我们用router.use()用来定义了路由中间件,并且把它应用到所有访问我们Node应用的请求上。打开浏览器访问http://localhost:8080/app
,我们可以看到console打印的信息:im the home page!
。
在代码中,中间件和路由的位置顺序非常重要。一个request请求到来时,它们会按照代码中的先后顺序依次执行。这就意味着如果你把中间件写在某一个路由的后面,路由会拦截这个request请求并完成响应,中间件则永远不会被执行。
带参数的路由 /hello/:name
我们想要在URL中传递一个人的名字name,让NODE应用输出 Hello name! 这里可以使用带参数的路由。
// server.js ... // 获取router实例 var router = express.Router(); ... // 带参数的路由 (http://localhost:8080/hello/:name) router.get('/hello/:name', function(req, res) { res.send('hello ' + req.params.name + '!'); }); // 把定义好的路由集成到Node应用中 app.use('/', router); ...
现在我们访问http://localhost:8080/hello/holly
就可以看到浏览器页面展示的信息:
Hello holly!
创建参数中间件
如果想要校验上面传入URL的人的名字,确保名字是符合规范的,我们需要在路由中间件中去校验URL中的参数name。它有个特殊的名字,参数中间件。我们可以使用express.param()
去创建它。
// server.js ... // 获取router实例 var router = express.Router(); ... // 参数中间件 校验name参数 router.param('name', function(req, res, next, name) { // 在这里进行校验操作 console.log('doing name validations on ' + name); // 校验通过我们把校验后的名字赋值给req对象 req.name = name; // 继续处理request请求,寻找匹配的路由 next(); }); // 带参数的路由 (http://localhost:8080/hello/:name) router.get('/hello/:name', function(req, res) { res.send('hello ' + req.name + '!'); }); // 把定义好的路由集成到Node应用中 app.use('/', router);
现在当我们访问到/hello/:name
路由,我们编写的参数中间件就会介入并做相应的校验处理。校验通过我们把校验后的名字赋值给req对象,并在相应的.get
路由中使用req.name
获取校验后的名字。打开浏览器,访问http://localhost:8080/hello/sally
,我们可以看到浏览器展示的信息:
Hello sally!
console控制台打印出:
doing name validations on sally
如果你使用RESTful API,你甚至可以校验token是否有效,来判断用户是否有权限访问。
链式路由
我们也可以直接在app对象上创建路由。利用app.route()
可以针对一个路由定义多个路由处理函数。例如,对/login
路由发起get请求,展示登录界面,同时也可以对/login
路由发起post请求,提交登录表单信息。我们就可以使用app.route来创建这个/login
路由。
// ROUTES // ============================================== app.route('/login') // 展示登录界面 (GET http://localhost:8080/login) .get(function(req, res) { res.send('this is the login form'); }) // 提交登录表单 (POST http://localhost:8080/login) .post(function(req, res) { console.log('processing'); res.send('processing the login form!'); }); ...
总结
使用Express 4.0中的路由,我们可以更灵活的定义路由:
- 多次使用
express.Router()
定义一组路由 - 使用
express.Router()
划分模块,并用app.use()
把他们整合起来 - 使用路由中间件对request请求进行预处理
- 使用参数中间
.param()
件对URL中参数进行校验 - 使用
app.route()
创建链式路由