我们知道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干嘛用?
分享到:
相关推荐
主要介绍了详解NodeJS框架express的路径映射(路由)功能及控制,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
Jello express服务端api映射框架要解决的问题前后端分离的开发方案中,前端的数据层被剥离出来而独立存在,通常数据层由服务端的api来提供,这就导致我们需要在Express的路由层反复的配置;一方面会导致重复劳动,...
用法创建一个映射,其中的键是受支持的控制器的版本,并且值是常规的ExpressJS路由功能签名。 const versionRouter = require ( 'express-version-route' )const routesMap = new Map ( )routesMap . set ( '1.0' , ...
功能处理它们之间的复杂关系映射。 LoopBack 是一个成熟的框架,可以轻松开始实施符合流行规范的 API 设计最佳实践。 [GEDDY JS] () Geddy.js 是 Node.js 的简单、结构化和原始的 MVC Web 框架,用于构建高级 Web ...
-> 在此路由的控制器中比 RN 更多用于验证 配置文件更新(用户模块) 射频 用户必须能够更新他们的姓名、电子邮件、密码; 核因子 它没有考虑任何 RNF; 注册护士 用户不能将他的电子邮件更改为其他用户已使用的...
Rainbow将所有HTTP请求路由映射到controllers文件夹,每个路由都作为URL的文件路径。安装$ npm install rainbow用法在您的快速应用程序主文件app.js : var express = require ( 'express' ) ;var rainbow = ...
这是基于REST API NodeJS的入门包,用于使用企业体系结构快速开发高级API服务。 安装 npm install 用法 开发模式 npm run start 生产 npm run start:prod 运行测试 npm run test 特征: 打字稿3+ NestJS 5(支持...
Vercel-Express Vercel Express和UI Webapp示例。... $ npm install vercel -g$ npm install$ vercelVercel将生成一个...代码后端见 前端参见 映射API路由(/ api / ...)和静态(UI)路由(/ ...)。 环境变量-示例: $ v
Express Nunjucks尾风CSS Express,Nunjucks和TailwindCSS的入门项目设置先决条件: 桌面版Docker 在项目的根目录中运行docker-compose up 。 它将以开发模式启动Postgres和Express应用程序服务器。 它将应用程序...
1.控制器层每个实体都有自己的控制器类,它在瘦层代表资源映射(路由) class PostsController extends BaseController { static get router () { router.get('/', this.actionRunner(actions.ListAction)) router....
主要软件包: Express负责创建路由,Middleware JWT负责令牌的30分钟持久性,维护用户的安全性和凭据,ORM Mongoose负责连接NoSQL数据库( MongoDB ),最后是Jest进行测试。 从导出的文件Insominia映射的路由: ...
语音堆栈具有PWA支持的FullStack Express和Vue.js应用程序的简约样板。 要了解此样板如何工作,请... 每个路由都映射到/api 。 默认情况下包括BodyParser 。例api / index.js const router = require ( 'express' )
这个仓库是做什么用的? Typescript中的Node.js应用...路由/控制器层该层正在快速应用程序中使用,并且取决于域层(服务)。 在这里,我们定义了可以从外部调用的路由。 这些服务始终被用作路由上的最后一个中间件,
:delivery_truck: Node.js,Express,Mongoose,Heroku,Atlas,Nodemon,PM2和Babel的样板。 // :rainbow: 该种子存储库提供以下功能: ----------必需品---------- 应用程序路由。 使用行业标准GraphQL...
节点应用程序层可以由Express Web服务器提供服务,也可以作为无服务器功能部署到云中。 空间数据必须存储在可访问云的PostGIS数据库中,以允许在数据源层中创建和缓存矢量图块。 应用程序控制和表示层作为ES6脚本...