1.1.2:node.js的路由控制
1.运行原理
在1.1.1节中,提到过app.js中app.get("/",routes.index)可以用以下代码取代:
1 2 3 4 5 | app.get( "/" , function (req,res){ res.render( "index" ,{title: "Express" }); }) |
这段代码可以这样理解:当访问主页时,调用ejs模板引擎来渲染index.ejs模板文件(即将所有的tittle变量替换成字符串Express),生成静态页面并渲染在浏览器上。
我就在这里做一个修改,既然以上的代码可以实现路由的功能,那么我可以去除routes/index.js文件,把实现路由功能的代码都写在app.js里,随着功能需求的增多,app.js会变得臃肿且难以维护,这不符合代码模块化的思想,所以呢,那些实现路由功能的代码都放在了routes/index.js中。官方给出的写法是在app.js中实现了简单的路由分配,然后再去index.js中找到相应的路由函数,最终实现路由功能。我准备这样做,把路由控制器和实现路由功能的函数都放到index.js里,在app.js只有一个总的路由接口。
打开app.js,做出修改和添加,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | /** * Module dependencies. */ var express = require( 'express' ); var routes = require( './routes' ); /* var user = require('./routes/user'); */ var http = require( 'http' ); var path = require( 'path' ); var app = express(); // all environments app.set( 'port' , process.env.PORT || 3000); app.set( 'views' , path.join(__dirname, 'views' )); app.set( 'view engine' , 'ejs' ); app.use(express.favicon()); app.use(express.logger( 'dev' )); app.use(express.json()); app.use(express.urlencoded()); app.use(express.methodOverride()); app.use(app.router); app.use(express. static (path.join(__dirname, 'public' ))); // development only if ( 'development' == app.get( 'env' )) { app.use(express.errorHandler()); } /* app.get('/', routes.index); app.get('/users', user.list); */ http.createServer(app).listen(app.get( 'port' ), function (){ console.log( 'Express server listening on port ' + app.get( 'port' )); }); //添加代码 routes(app); |
打开index.js,修改如下
1 2 3 4 5 6 7 8 9 | /* * GET home page. */ module.exports = function (app){ app.get( "/" , function (req,res){ res.render( "index" ,{title: "Express" }); }); }; |
然后,你再次在app.js目录上,打开终端,输入node app,访问localhost:3000,你会发现修改后的效果和修改前的效果没有变化。为何?这里我在routes/index.js中通过module.express导出了一个函数接口,在app.js中通过require加载了index.js,然后通过routes(app)调用了index.js导出的函数;
2.路由规则
Express封装了多种http请求方式,常用的有get和post,即app.get()和app.post();app.get()和app.post()的第一个参数都为请求的路径,第二个参数为处理请求的回调函数,回调函数有两个参数,请求和响应,习惯用req和res表示。路径请求及对应的获取路径有以下几种形式:
(1)req.query
1 2 3 4 5 6 7 8 9 | //GET /murenziwei?like=node console.log(req.query.like) //=>"node" //GET /love?name=liwei&birthday[year]=2222&birthday[month]=11 console.log(req.query.name); //=>"liwei" console.log(req.query.birthday.year); //=>"2222" console.log(req.query.birthday.month); //=>"11" |
(2) req.body
1 2 3 4 5 6 7 | //POST book[name]=凡人修仙传&book[author]=忘语 console.log(req.body.book.name) //=>凡人修仙传 console.log(req.body.book.author); //=>忘语 //POST {"name":"诛仙"} console.log(req.body.name); //=>诛仙 |
(3)req.params
1 2 3 4 5 | //GET /user/murenziwei console.log(req.params.name) //=>"murenziwei" //GET /language/typescript/node.js console.log(req.params[0]); //=>"typescript/node.js" |
(4)req.param(xxx)
1 2 3 4 5 6 7 8 | //GET /language/typescript/node.js?name=liwei console.log(req.param( 'name' )) //=>"liwei" //POST name=liwei console.log(req.param( 'name' )); //=>"liwei" // /user/liwei for /user/:name console.log(req.param( 'name' )); //=>"liwei" |
由上述的代码,总结出以下获取路径的含义:
- req.query:处理get请求,获取get请求体
- req.body:处理post请求,获取post请求体
- req.params:处理/:xxx形式的get或post请求,获取请求参数
- req.param():处理get和post请求,但查找优先级由高到低为:req.params=>req.body=>req.query
听说路径规则还支持正则表达式,如果你感兴趣的话,不妨一试。
3.路由规则
在浏览器上访问localhost:3000,会显示如下图
![](https://i-blog.csdnimg.cn/blog_migrate/3f2684f2d985aeabb2d8ddc69e288a13.png)
如果我要访问localhost:3000/hello这种不存在的页面时就会显示如下图
![](https://i-blog.csdnimg.cn/blog_migrate/d64fe4e824e0920970511060b6f03445.png)
这是因为不存在/hello的路由规则,而且它也不是一个public目录下的文件,所有express返回了404Not Found的错误。下面我来添加一个路由规则,使得当访问localhost:3000/hello时,页面显示“你好,路由规则!”
修改index.js,在app.get("/")后面添加一条路由规则
1 2 3 4 5 6 7 8 9 10 11 12 | /* * GET home page. */ module.exports = function (app){ app.get( "/" , function (req,res){ res.render( "index" ,{title: "Express" }); }); app.get( "/hello" , function (req,res){ res.send( "你好,路由规则!" ); }); }; |
修改后,再来在终端重新输入node app,打开浏览器访问local host:3000/hello页面显示图下
![](https://i-blog.csdnimg.cn/blog_migrate/e4c1c1b9f8e7f762812b76bd3eaa80ec.png)
看到这,是不是很简单!那么总结一下,我主要讲了基本的路由规则以及如何添加一条路由规则的知识点。
流过血的手指弹出世间绝唱