我 们知道Express是一个基于NodeJS的非常优秀的服务端开发框架,本篇CSSer将提供express框架的route和route control章节,route实现了客户端请求的URL的路径映射功能,暂且译为路由或URL映射吧。如果你还是不太理解,相信看完本篇文章将会有些收 获的。

路由(URL映射)

Express利用HTTP动作提供了有意义并富有表现力的URL映射API,例如我们可能想让用户帐号的URL看起来像“/user/12”的样子,下面的例子就能实现这样的路由,其中与占位标识符(本例为:id)相关的值可以被req.params获取到。

app.get('/user/:id', function(req, res){
    res.send('user ' + req.params.id);
});

上例中当我们访问/user/12时返回“user 12”,CSSer注:app.get相当于在服务器注册了一个监听get请求事件的侦听器,当请求的URL满足第一个参数时,执行后面的回调函数,该过程是异步的。

路由是一个可以被内部编译成正则表达式的简单字符串,比如当/user/:id被编译后,被内部编译后的正则表达式字符串看起来会是下面的样子(简化后):

\/user\/([^\/]+)\/?

要实现复杂点的,我们可以传入正则表达式直接量,因为正则捕获组是匿名的因此我们可以通过req.params进行访问,第一个捕获组应该是req.params[0],第二个应该是req.params[1],以此类推。

app.get(/^\/users?(?:\/(\d+)(?:\.\.(\d+))?)?/, function(req, res){
    res.send(req.params);
});

通过Linux的curl命令来测试我们定义的路由:

$ curl http://cssercom:3000/user
[null,null]
$ curl http://cssercom:3000/users
[null,null]
$ curl http://cssercom:3000/users/1
["1",null]
$ curl http://cssercom:3000/users/1..15
["1","15"]

下面是一些路由例子,以及与之相匹配的关联路径:

"/user/:id"
/user/12 "/users/:id?"
/users/5
/users "/files/*"
/files/jquery.js
/files/javascripts/jquery.js "/file/*.*"
/files/jquery.js
/files/javascripts/jquery.js "/user/:id/:operation?"
/user/1
/user/1/edit "/products.:format"
/products.json
/products.xml "/products.:format?"
/products.json
/products.xml
/products "/user/:id.:format?"
/user/12
/user/12.json

另外,我们可以通过POST方式提交json数据,然后利用bodyParser中间件解析json请求体并把json数据返回给客户端:

var express = require('express')
  , app = express.createServer(); app.use(express.bodyParser()); app.post('/', function(req, res){
  res.send(req.body);
}); app.listen(3000);

通常我们所使用的占位符(比如/user/:id)都没有任何限制,即用户可以传入各种各样数据类型的id值,如果我们希望限制用户id为数字,可以这样写“/user/:id(\d+)”,这样就能保证只有该占位符数据类型为数值类型才会进行路由的相关处理。

路由控制

一 个应用中可以定义多个路由,我们可以控制以令其转向下一个路由,Express提供了第三个参数即next()函数。当一个模式不被匹配时,控制将被转回 Connect(Express基于Connect模块),同时中间件会继续按照它们在use()中增加的顺序来执行。当多个定义的路由都可能匹配同一个 URL时也是如此,除非某个路由并不调用next()且已将响应输出到客户端,否则它们也将按顺序执行。

app.get('/users/:id?', function(req, res, next){
    var id = req.params.id;
    if (id) {
        // 一回注:如果在这里就将响应内容输出给客户端,那么后续的URL映射将不会被调用
    } else {
        next(); // 将控制转向下一个符合URL的路由
    }
}); app.get('/users', function(req, res){
    // do something else
});

app.all()方法可以对所有HTTP动作应用单一调用入口,这在有些情况下很有用。下面我们使用该功能来从我们的模拟数据库中加载一个用户,并把它分配给req.user。

var express = require('express')
  , app = express.createServer(); var users = [{ name: 'www.csser.com' }]; app.all('/user/:id/:op?', function(req, res, next){
  req.user = users[req.params.id];
  if (req.user) {
    next();
  } else {
    next(new Error('cannot find user ' + req.params.id));
  }
}); app.get('/user/:id', function(req, res){
  res.send('viewing ' + req.user.name);
}); app.get('/user/:id/edit', function(req, res){
  res.send('editing ' + req.user.name);
}); app.put('/user/:id', function(req, res){
  res.send('updating ' + req.user.name);
}); app.get('*', function(req, res){
  res.send('what???', 404);
}); app.listen(3000);

路由参数预处理

本节为后补(2011-4-16)。

路由参数预处理通过隐式的数据处理,可以大幅提高应用代码的可读性和请求URL的验证。假如你经常性的从几个路由获取通用数据,如通过/user/:id加载用户信息,通常我们可能会这样做:

app.get('/user/:userId', function(req, res, next){
  User.get(req.params.userId, function(err, user){
    if (err) return next(err);
    res.send('user ' + user.name);
  });
});

利 用预处理后参数可以被映射到回调函数,从而可以提供诸如验证、强制性改变值,甚至从数据库中加载数据等功能。下面我们将调用app.param()并传入 我们希望映射到某个中间件的参数,可以看到我们接收了包含占位符(:userId)值的id参数。在这里可以与平常一样进行用户数据加载以及错误处理,并 能简单的通过调用next()将控制权转向下一个预处理或路由(路径控制)。

app.param('userId', function(req, res, next, id){
  User.get(id, function(err, user){
    if (err) return next(err);
    if (!user) return next(new Error('failed to find user'));
    req.user = user;
    next();
  });
});

这样做,不仅向上面提到的可以大幅提高路由的可读性,还能在整个应用中共享该部分的逻辑实现,达到复用目的。

app.get('/user/:userId', function(req, res){
  res.send('CSSer用户为 ' + req.user.name);
});

对于简单的情况如路由占位符验证和强迫改变值,只需要传入1个参数(支持1个参数),期间抛出的异常将自动传入next(err)。

app.param('number', function(n){ return parseInt(n, 10); });

也可以同时将回调函数应用到多个占位符,比如路由/commits/:from-:to来说,:from和:to都是数值类型,我们可以将它们定义为数组:

app.param(['from', 'to'], function(n){ return parseInt(n, 10); });

结语

通 过本文的学习,我们应该有些感觉了,NodeJS不仅仅可以实现我们产品的服务端逻辑,同时我们还可以利用Javascript做服务器编程,注意是服务 器,也就是说,我们可以利用Javascript来定制以往只能在apache中才可以做到的功能。NodeJS还需要rewrite吗?路径映射更简单 更强大,还要rewrite干嘛用?

来自:http://my.oschina.net/u/1582119/blog/310639

NodeJS框架express的路径映射(路由)功能及控制的更多相关文章

  1. [转] NodeJS框架express的途径映射(路由)功能及控制

    NodeJS框架express的路径映射(路由)功能及控制 我们知道Express是一个基于NodeJS的非常优秀的服务端开发框架,本篇CSSer将提供express框架的route和route co ...

  2. NodeJS 框架 Express 从 3.0升级至4.0的新特性

    NodeJS 框架 Express 从 3.0升级至4.0的新特性 [原文地址:√https://scotch.io/bar-talk/expressjs-4-0-new-features-and-u ...

  3. 知名nodeJS框架Express作者宣布弃nodeJS投Go

    知名 nodeJS 框架 Express 的作者 TJ Holowaychuk 在 Twitter 发推并链接了自己的一篇文章,宣布弃 nodeJS 投 Go. 他给出的理由是:Go 语言和 Rust ...

  4. nodejs框架express快速开始

    认识express 创建应用 get请求 简述中间件 all方法 use方法1 use方法2 回调函数 获取主机.路径名 Get请求 - query Get请求 - param Get请求 - par ...

  5. 一步一步重写 CodeIgniter 框架 (2) —— 实现简单的路由功能

    在上一课中,我们实现了简单的根据 URI 执行某个类的某个方法.但是这种映射没有扩展性,对于一个成熟易用的框架肯定是行不通的.那么,我们可以让 框架的用户 通过自定义这种转换来控制,用 CI 的术语就 ...

  6. 引用nodejs的url模块实现url路由功能

    我们在本地创建服务器之后需要写不同的后缀名来访问同一个站点的不同页面,如果不实现路由功能.则每次访问localhost:3000 不论后面写什么  比如localhost:3000/index.loc ...

  7. nodejs框架express准备登录

    目录: 安装模板 静态资源 添加视图 渲染视图 url重定向 模板引擎 从本节课程开始我们要使用express框架实现一个简单的用户登陆功能,让我们先准备一下相关资源. 在nodejs中使用expre ...

  8. nodejs框架express实现登录

    目录: 访问视图 Post请求 Post请求 - body(1) Post请求 - body(2) Post登陆1 Post登陆2 页面访问控制1 页面访问控制2 访问视图 前面我们已经添加了视图模板 ...

  9. CentOS安装运行NodeJS框架Express

    安装依赖包 yum -y install gcc make gcc-c++ openssl-devel wget 下载/解压NodeJs wget http://nodejs.org/dist/v0. ...

随机推荐

  1. Linux下的一些名词解释

    libffi (以下E文摘自http://www.sourceware.org/libffi/) A Portable Foreign Function Interface Library. Comp ...

  2. 胡乱摸的NOIP2017游记和总结

    来自YZK的总结 本篇总结主要分成两部分:NOI Professional游记和平日的刷题训练. 今年的NOI Professional TG的难度在洛谷上标记为:二黄一绿三紫.恭喜NOIP今年全面脱 ...

  3. C/C++基础----IO库

    IO对象无拷贝或赋值,通常以引用形式传递. IO库条件状态 strm::iostate 一种机器相关的类型,提供了表达条件状态的完整功能 strm::badbit 用来指出流已经崩溃 strm::fa ...

  4. bzoj2464 小明的游戏

    Description 小明最近喜欢玩一个游戏.给定一个n * m的棋盘,上面有两种格子#和@.游戏的规则很简单:给定一个起始位置和一个目标位置,小明每一步能向上,下,左,右四个方向移动一格.如果移动 ...

  5. Spring Cloud构建微服务架构(七)消息总线

    先回顾一下,在之前的Spring Cloud Config的介绍中,我们还留了一个悬念:如何实现对配置信息的实时更新.虽然,我们已经能够通过/refresh接口和Git仓库的Web Hook来实现Gi ...

  6. 1077 Kuchiguse (20 分)

    1077 Kuchiguse (20 分) The Japanese language is notorious for its sentence ending particles. Personal ...

  7. golang web框架 beego 学习 (一) 环境搭建

    下面的命令我都是在$GOPATH的路径下执行的: 1. 首先下载beego框架: go get github.com/astaxie/beego (注意:运行上面命令时没有反应,需要在etc/host ...

  8. 在docker中运行jenkins实现代码自动发布到测试服务器

    在docker中运行jenkins 用的镜像是apline版:lts-alpine,并设置正确的时区. docker run --name jenkins_master -d \ -p 8081:80 ...

  9. 链接mysql的两种方法

    使用mysql二进制方式连接 您可以使用MySQL二进制方式进入到mysql命令提示符下来连接MySQL数据库. 实例 以下是从命令行中连接mysql服务器的简单实例: [root@host]# my ...

  10. MongoDB——更新操作(Update)c#实现

    c#实现 Mongodb存储[文档局部更新] 如下: 递归更新字段  ,构建UpdateDefinition   /// <summary>   /// 构建更新操作定义   /// &l ...