在之前的文章中我们说到express
为我们提供的最强大的能力就是一套超级简单且强大的路由系统,那到底什么是路由呢?
路由是指如何定义应用的端点(URIs
)以及如何响应客户端的请求。【相关教程推荐:nodejs视频教程】
(资料图片仅供参考)
路由是由一个 URI
、HTTP
请求(GET
、POST
等)和若干个句柄组成,它的结构如下:
app.METHOD(path, [callback...], callback)
登录后复制
app
是 express
对象的一个实例METHOD
是一个 HTTP
请求方法path
是服务器上的路径callback
是当路由匹配时要执行的函数这篇文章我们将深入去学习express
的路由系统,让我们开始吧!
1、基础路由
先定义一个基础的路由:
const express = require("express");// app对象const app = express();app.get("/", (req, res) => { res.send("匹配/");});
登录后复制
上面的例子表示的是一个路径为/
的GET
请求路由,即当用户使用GET
请求访问/
时会执行(req, res) =>{res.send("匹配/");}
函数。
路由路径和请求方法一起定义了请求的端点:
// 匹配 / 路径的get请求app.get("/", (req, res) => { res.send("匹配 / 路径的get请求");});// 匹配 / 路径的post请求app.post("/", (req, res) => { res.send("匹配 / 路径的post请求");});// 匹配 / 路径的put请求app.put("/", (req, res) => { res.send("匹配 / 路径的put请求");});// 匹配 / 路径的delete请求app.delete("/", (req, res) => { res.send("匹配 / 路径的delete请求");});
登录后复制
观察上面的路由你会发现它们的请求路径是一样的,只是请求方式不同,这是允许的,因为相同路径的请求只要请求方法不同最后就会进入到不同的处理函数中。
这种风格的写法称为RES Tful,在开发API
接口中比较推荐使用。
2、路径匹配
express
的路由可以进行模糊匹配,这是因为express
的路由路径可以是字符串、字符串模式或者正则表达式。
字符串匹配
当路径使用字符串时进行的就是普通的匹配,路径是什么就匹配什么:
// 匹配根路径的请求app.get("/", function (req, res) { res.send("root");});// 匹配 /about 路径的请求app.get("/about", function (req, res) { res.send("about");});
登录后复制
字符串模式匹配
在字符串的基础上添加一些额外的语法(如下)称为字符串模式。
?
表示可选:id
表示使用id
字段占位+
表示可出现多次(至少一次)*
表示任意使用字符串模式的路径:
// 匹配 /acd 和 /abcd:?前边的字符代表可选app.get("/ab?cd", function (req, res) { res.send("ok");});// 匹配 /ab/*******::id代表占位,这个id是自定义的(你也可以写:aa,:bb等),之后能用来获取/ab/后的参数app.get("/ab/:id", function (req, res) { res.send("/ab/*******");});// 匹配 /abcd,/abbcd,/abbbcd等,+号前的字符可以连续出现多个app.get("/ab+cd", function (req, res) { res.send("/ab+cd");});// 匹配 /abcd,/abxcd,/abBIHIHIcd,/ab1456cd等,*号代表任意字符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");});
登录后复制
正则匹配
express
路由匹配中最强大的一点就是它能够根据正则来进行匹配(虽然这在开发中用处不多)。
使用正则表达式的路由路径:
// 匹配任何路径中含有 a 的路径:app.get(/a/, function (req, res) { res.send("/a/");});// 匹配 butterfly、dragonfly,不匹配 butterflyman、dragonfly man等app.get(/.*fly$/, function (req, res) { res.send("/.*fly$/");});
登录后复制
3、处理函数
可以为请求处理提供多个回调函数,其行为类似 中间件。
唯一的区别是这些回调函数有可能调用 next("route")
或next("router")
方法而略过其他路由回调函数。
多函数
使用多个回调函数处理路由(记得指定 next
对象):
// 直接添加多个回调函数app.get( "/", (req, res, next) => { console.log("第一个执行"); next(); }, (req, res, next) => { console.log("第二个执行"); next(); // next("route") next中添加route参数时会跳过之后的回调函数 }, (req, res) => { console.log("最后一个执行"); // 返回数据内容 res.send("home"); });
登录后复制
函数数组
还可以以数组的形式添加回调函数:
const f1 = (req, res, next) => { console.log("第一个执行"); next();};const f2 = (req, res, next) => { console.log("第二个执行"); next();};const f3 = (req, res) => { console.log("最后一个执行"); res.send("login");};app.get("/login", [f1, f2, f3]);
登录后复制
混合使用
混合使用函数和函数数组处理路由:
const fn1 = function (req, res, next) { console.log("fn1"); next();};var fn2 = function (req, res, next) { console.log("fn2"); next();};app.get( "/about", [fn1, fn2], function (req, res, next) { console.log("fn3"); next(); }, function (req, res) { res.send("about"); });
登录后复制
应用
可以利用该机制为路由定义前提条件,如果在现有路径上继续执行没有意义,则可将控制权交给剩下的路径。
例如在开发中经常使用到的token
验证,假如现在共有三个接口:
/login
用户登录的接口,不需要token
验证/home
只有token
验证通过才能访问/user
只有token
验证通过才能访问这时我们就可以这样开发:
// 不需要token验证app.get("/login", (req, res) => { res.send("登录");});// 验证token的函数(可插拔,可复用的中间件)const isToken = (req, res, next) => { // 验证token是否过期,isVaild代表token是否有效 // 一些操作 const isVaild = true; // 假设验证通过 if (isVaild) { // 验证通过了就调用next向下执行 console.log("token验证通过"); // 如果想要在回调函数之间传递数据,我们可以选择将数据挂载到res参数上 res.ailjx = "海底烧烤店ai"; next(); } else { // 返回错误 // 这里res.send后后面的回调函数就不会再执行了 res.send("token验证失败!"); }};// 只有token有效时才生效的接口app.get("/home", [isToken], (req, res) => { // 返回数据内容 // res.ailjx:获取验证token的函数在res上绑定的数据 res.send("home" + res.ailjx);});app.get("/user", [isToken], (req, res) => { // 返回数据内容 res.send("user");});
登录后复制
上面我们将验证token
的函数抽离了出去,之后在需要该函数的路由中直接引用即可,这就避免了我们需要在每个路由中都写一遍token验证的繁琐过程。
4、路由级中间件
上面我们定义的路由都是直接绑定到了app
对象上,这称为应用级中间件。
当我们的路由过多时,这势必会变得难以维护,于是就出现了路由级中间件用来将我们的路由抽离出来,路由级中间件和应用级中间件一样,只是它绑定的对象为 express.Router()
。
// apiRouter.jsconst express = require("express");// router对象const router = express.Router();// 路由级别中间件:api路由router.get("/home", (req, res) => { res.send({ list: [1, 2, 3, 4], });});router.get("/about", (req, res) => { res.send({ name: "ailjx", age: 18, });});// 导出module.exports = router;
登录后复制
// server.jsconst express = require("express");const app = express();// 导入api路由const apiRouter = require("./route/apiRouter");// 使用app.use将路由挂载至应用app.use(apiRouter);app.listen(3000, () => { console.log("start");});
登录后复制
上面我们使用路由级中间件定义路由,之后通过模块化导入的形式将路由导入,再使用app.use
将路由挂载至应用,这种代码结构就使得整个项目变得更加容易维护。
在挂载路由时我们也可以指定一级路径:
// 如果use具有第一个路径参数,如下面的/api,则/api相当于是一级路径,apiRouter里的路径就相当于二级路径了app.use("/api", apiRouter);
登录后复制
这样挂载后的路由访问时就需要加上/api
,如:
/api/home
/api/about
结语
本篇文章详细介绍了express
路由的使用,并由此引入路由级中间件的使用(关于express中间件
博主之后会出单独的文章进行讲解)。
更多node相关知识,请访问:nodejs 教程!
以上就是值得了解的Node express路由使用技巧的详细内容,更多请关注php中文网其它相关文章!