Node.js之express路由

266 阅读5分钟

路由

路由用于确定应用程序如何响应对特定端点的客户机请求,包含一个 URI(或路径)和一个特定的 HTTP 请求方法(GET、POST 等)。

每个路由可以具有一个或多个处理程序函数,这些函数在路由匹配时执行。

路由的基本结构:

app.METHOD(PATH,HANDLER)

其中:

  • appexpress 的实例。

  • METHOD 是 HTTP 请求方法。

  • PATH 是服务器上的路径。

  • HANDLER 是在路由匹配时执行的函数。

一个最简单的路由示例:

const express = require('express')
const app = express()
//当对主页发出 GET 请求时,响应“hello world”
app.get('/', (req, res) => {
    res.send('hello word')
})

路由方法

不同的类型的HTTP请求需要用对应的路由方法来响应,下面两个路由方法分别响应GET和POST请求:

//响应GET请求
app.get('/', (req, res) => {
    res.send('get请求会触发')
})
//响应POST请求
app.post('/', (req, res) => {
    res.send('post请求会触发')
})

Express支持以下派生自HTTP的路由方法:

checkoutmkcolpurge
copymoveput
deletem-searchreport
getnotifysearch
headoptionssubscribe
lockpatchtrace
mergepostunlock
mkactivityunsubscribe

有一个特殊的路由方法app.all(),只要对对应路径(下面例子是/index)的请求都会执行处理程序,无论使用的是GET、POST、DELETE、PUT还是其他请求方法:

app.all('/index', (res, req) => {
    console.log('执行了all的处理程序');
    next() //将控制权传递给下一个中间件函数
})

路由路径

路由路径可以是字符串、字符串模式或正则表达式。

以下是基于字符串的路由路径的一些示例。

此路由路径将请求与根路由 / 匹配。

app.get('/', function (req, res) {
  res.send('root');
});

此路由路径将请求与 /about 匹配。

app.get('/about', function (req, res) {
  res.send('about');
});

此路由路径将请求与 /random.text 匹配。

app.get('/random.text', function (req, res) {
  res.send('random.text');
});

以下是基于字符串模式的路由路径的一些示例。

此路由路径将匹配 acdabcd

app.get('/ab?cd', function(req, res) {
  res.send('ab?cd');
});

此路由路径将匹配 abcdabbcdabbbcd 等。

app.get('/ab+cd', function(req, res) {
  res.send('ab+cd');
});

此路由路径将匹配 abcdabxcdabRABDOMcdab123cd 等。

app.get('/ab*cd', function(req, res) {
  res.send('ab*cd');
});

此路由路径将匹配 /abe/abcde

app.get('/ab(cd)?e', function(req, res) {
 res.send('ab(cd)?e');
});

基于正则表达式的路由路径的示例:

此路由路径将匹配名称中具有“a”的所有路由。

app.get(/a/, function(req, res) {
  res.send('/a/');
});

此路由路径将匹配 butterflydragonfly,但是不匹配 butterflymandragonfly man 等。

app.get(/.*fly$/, function(req, res) {
  res.send('/.*fly$/');
});

路由参数

路由参数设置在路由路径上,用于获取路由路径中指定位置的值,捕获的值填充在req.params对象中,路径中指定的路由参数的名称作为各自的键。

在路由路径中用“ :”指定路由参数:

//路由路径  
// userId 和 bookId 被指定为路由参数
'/users/:userId/books/:bookId'
//请求url
'http://localhost:3000/users/34/books/8989'
app.get('/users/:userId/books/:bookId', function (req, res) {
  res.send(req.params) //{ "userId": "34", "bookId": "8989" }
})

特殊情况:带有连字符(-) 和(.)的路径

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 path: /user/:userId(\d+)
Request URL: http://localhost:3000/user/42
req.params: {"userId": "42"}

路由处理程序

单个回调函数可以处理路由。例如:

app.get('/example/a', function (req, res) {
  res.send('Hello from A!')
})

多个回调函数可以处理一个路由(确保指定 next 对象)。例如:

app.get('/example/b', function (req, res, next) {
  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) {
  res.send('Hello from C!')
}

app.get('/example/c', [cb0, cb1, cb2])

响应方法

下表中响应对象 (res) 上的方法可以向客户端发送响应,并终止请求-响应周期。如果未从路由处理程序调用这些方法,则客户端请求将保持挂起状态。

方法描述
res.download()提示将要下载文件。
res.end()结束响应进程。
res.json()发送 JSON 响应。
res.jsonp()在 JSONP 的支持下发送 JSON 响应。
res.redirect()重定向请求。
res.render()呈现视图模板。
res.send()发送各种类型的响应。
res.sendFile()以八位元流形式发送文件。
res.sendStatus()设置响应状态码并以响应主体形式发送其字符串表示。

app.router()

可以使用app.router()为同一个路由路径创建可连接的路由处理程序,这样可以减少代码冗余,使路由更加模块化。

下面是使用 app.route() 定义的链式路由处理程序的示例。

app.route('/book')
  .get(function (req, res) {
    res.send('Get a random book')
  })
  .post(function (req, res) {
    res.send('Add a book')
  })
  .put(function (req, res) {
    res.send('Update the book')
  })

express.Router

使用espress.Router类创建模块化、可装载的路由处理程序。

以下示例将路由器创建为模块,在其中装入中间件,定义一些路由,然后安装在主应用程序的路径中。

在应用程序目录中创建名为 birds.js 的路由器文件,其中包含以下内容:

const express = require('express');
const router = express.Router();

// middleware that is specific to this router
router.use(function timeLog(req, res, next) {
  console.log('Time: ', Date.now());
  next();
});
// define the home page route
router.get('/', function(req, res) {
  res.send('Birds home page');
});
// define the about route
router.get('/about', function(req, res) {
  res.send('About birds');
});

module.exports = router;

接着,在应用程序中装入路由器模块:

const birds = require('./birds');
...
app.use('/birds', birds);

此应用程序现在可处理针对 /birds/birds/about 的请求,调用特定于此路由的 timeLog 中间件函数。