路由是指应用程序的端点(URL)如何响应客户端请求。
我们可以使用app与HTTP方法相对应的Express对象的方法来定义路由。
例如:app.get() 处理GET请求和 app.post() POST请求。
还可以使用 app.all() 处理所有的HTTP方法,并使用 app.use() 将中间件指定为回调函数。
这些路由方法指定在应用程序收到对指定路由(端点)和HTTP方法的请求时调用的回调函数(有时称为“处理函数”,换句话说,应用程序“侦听”与指定的路由和方法相匹配的请求,并且当他检测到匹配项时,它将调用指定的回调函数).
实际上,路由方法可以具有多个回调函数作为参数。对于多个回调函数,重要的是提供next回调函数的参数,然后next()在函数体内调用以将控制权移交给下一个回调。
const express = require('express');
const app = express();
app.get('/',function(req,res){
res.send("hello world");
})
路由方法是从HTTP方法之一派生的,并添加到express 该类的实例。
以下代码是为GET 和 POST 方法定义到应用根目录的路由的实例。
// GET method route
app.get('/',function(req,res){
res.send("Get request to the homepage");
})
// post method route
app.post('/',function(req,res){
res.send("Post request to the homepage");
})
Express支持与所有HTTP请求方法相对应的方法: get, post等。
有一种特殊的路由方法,app.all()用于为所有HTTP 请求方法的路径加载中间件功能。例如:无论是使用GET, POST, PUT, DELETE还是http模块支持的任何其他HTTP请求方法,都会对路由 /secret 的请求执行以下处理程序.
app.all("/secret",function(req,res,next){
console.log("Accessing the secret section...");
next() //pass control to the next handler
})
路由路径与请求方法相结合,定义了可以进行请求的端点。路由路径可以是字符串,字符串模式或正则表达式。
字符 ?,+,* 和()是他们的正则表达式的对应的子集。连字符 (-)和点(.)由基于字符串的路径按字面意义进行解释。
如果您需要 $ 在路径字符串中使用美元字符 (),请将其转移([并括在和中]),例如:“/data/$book”处用于请求的路径字符串将为 /data/([ \ $])book
Express使用 path-to-regexp 来匹配路由路径
(1)此路由路径会将请求匹配到根路由 /
app.get('/',function(req,res){
res.send("root");
})
(2)此路由路径会将请求匹配到 /about
app.get('/about',function(req,res){
res.send("about");
})
(3)此路由路径会将请求匹配到 /random.text
app.get('/random.text',function(req,res){
res.send("random.text");
})
(1)此路由路径将与 acd和匹配 abcd
app.get('/ab?cd',function(req,res){
res.send("ab?cd");
})
(2)此路线的路径将会匹配 abcd ,abbcd ,abbcd等等
app.get('/ab+cd',function(req,res){
res.send("ab+cd")
})
(3)此路径将会匹配 abcd,abxcd,abRANDOMcd,ab123cd
app.get('/ab*cd',function(req,res){
res.send("ab*cd")
})
(4)此路由路径将与 /abe 和匹配 /abcde
app.get('/ab(cd)?e',function(req,res){
res.send("ab(cd)?e")
})
(1)此路由路径将匹配其中带有 a 的任何内容
app.get(/a/,function(req,res){
res.send('/a/')
})
(2)此路由路径将匹配 butterfly 和dragonfly,但不butterflyman,dragonflyman等
app.get(/.*fly$/,function(req,res){
res.send('fly$')
})
路径参数被命名为URL段,用于捕获URL中在其位置处指定的值。捕获的值将填充到req.params对象中,并将路径中指定的route参数的名称作为其各自的键。
Route path: /users/userId/books/:bookID
Request URL: http://localhost:3000/users/34/books/8989
req.params:{"userId":"34","bookId":"8989"}
要使用路由参数定义路由,只需要在路由路径中指定路由参数,如下所示:
app.get('/users/:userId/books/:bookId',function(req,res){
console.log(req.params);
res.send('/users/userId/books/:bookID')
})
路由参数的名称必须由“文字字符”([A-Za-z0-9])组成。由于连字符(-)和点(.)是按字面解释的,因此可以将他们与路由参数一起使用,以实现有用的目的。
Route path: /flights/:from-:to
Request URL: http://localhost:3000/flights/LAX-SFO
req.params:{"from":"LAX","to":"SFO"}
Route path: /plantae/:genus.:species
Request URL: http://localhost:3000/plantae/Prunus.persica
req.params:{"genus":"Prunus","species":"persica"}
要更好地控制由route参数匹配的确切字符串,可以在括号(())后面附上一个正则表达式:
Route path: /user/:userId(\d+)
Request URL: http://localhost:3000/user/42
req.params:{"userId":"42"}
//\有转义的原因 所以需要有两条杠
app.get('/users/:userId(\\d+)',function(req,res){
console.log(req.params);
res.send('/user/:userId(\d+)')
})
可以提供行为类似于中间件的多个回调函数来处理请求。唯一的例外是这些回调可以会调用next(‘route’) 以绕过其余的路由回调。可以使用此机制在路由上施加先决条件,然后在没有理由继续使用当前路由的情况下将控制权传递给后续路由。
路由处理程序可以采用函数、函数数组或者二者组合的形式。如下示例所示。
app.get('/example/a',function(req,res){
res.send("Hello From A")
})
app.get('/example/b',function(req,res){
console.log("the response will be sent by the next function")
next();
},function(req,res){
res.send("Hello From B")
})
var cb0 = function(req,res,next){
console.log("CB0");
next();
}
var cb1 = function(req,res,next){
console.log("CB1");
next();
}
var cb2 = function(req,res,next){
res.send("Hello from C")
}
app.get('/example/c',[cb0,cb1,cb2])
var cb0 = function(req,res,next){
console.log("CB0");
next();
}
var cb1 = function(req,res,next){
console.log("CB1");
next();
}
app.get('/example/d', [cb0, cb1], function (req, res, next) {
console.log("the response will be sent by the next function")
next();
}, function (rew, res) {
res.send("Hello from D")
})
res 下表中响应对象()上的方法可以将响应发送到客户端,并终于请求-响应周期。如果没有从路由处理程序调用这些方法,则客户端请求将被挂起。
方法 | 描述 |
---|---|
res.download() | 提示要下载的文件 |
res.end() | 结束响应过程 |
res.json() | 发送JSON响应 |
res.jsonp() | 发送JSONP支持的响应 |
res.redirect() | 重定向请求 |
res.render() | 提渲视图模版 |
res.send() | 发送各种类型的响应 |
res.sendFile() | 将文件作为八位字节流发送响应 |
res.sendStatus() | 设置响应状态代码,并将字符串表示形式发送为响应文 |
可以使用来为路由路径创建可链接的路由处理程序 app.route 。由于路径实在单个位置指定的,因此创建模块化路由非常有帮助,减少冗余和错别字也很有帮助。
这是使用定义的连接路由处理程序的示例 app.route()
app.route("/book")
.get(function(req,res){
res.send("get a book")
})
.post(function(req,res){
res.send(" add a book")
})
.put(function(req,res){
res.send(" update a book")
})
使用express.Router该类创建模块化的、可安装的路由处理程序。一个Router示例是一个完整的中间件和路由系统;因此,它通常被称为“迷你应用程序”。
以下示例将路由器创建为模块,在其中加载中间件功能,定义一些路由,并将路由器模块安装在主应用程序的路径上。
bird.js 在app目录中创建一个名为以下内容的路由器文件:
const express = require('express');
const router = express.Router();
router.use(function timeLog(req, res, next) {
console.log("Time:", Date.now());
next();
})
router.get('/', (req, res, next) => {
res.send("Birds home page")
})
router.post('/about', async (req, res) => {
res.send('about birds foo')
})
//导出路由实例
module.exports = router;
然后在应用程序中加载路由器模块:
const bird = require("./bird")
//...
app.use('/bird',bird)
该应用程序现在将能够处理对 /bird 和请求 /bird/about ,以及调用timeLog 特定于该路由的中间件功能。