搜索

首页  >  问答  >  正文

java - 如何编写一个web 框架的 url 路由

如果路由都只是 url 字符串完全匹配的,我可以用 hashmap ,理想情况 O(1) 复杂度。
但是我想在 url 匹配中支持 通配符,那么最简单的实现方法,我就直接用正则了,但是匹配复杂度就变成 O(n)了,这样感觉不是很好。。。

如何解决这个问题

PHP中文网PHP中文网2809 天前489

全部回复(4)我来回复

  • 巴扎黑

    巴扎黑2017-04-18 09:50:46

    为什么不用树来存路由的地址呢?
    如图,每一个方框都是一个 Map
    当你请求 /user/111/profile/books/222的时候先将 url 打散
    ['/' , '111' , 'profile' , 'books' , '222']
    先搜索第一层有没有一个 / 节点
    然后搜索第二层有没有一个 111 节点 ,没有的话进入 * 节点
    然后所搜第三层有没有一个 profile 节点
    以此类推

    回复
    0
  • PHP中文网

    PHP中文网2017-04-18 09:50:46

    https://github/bephp/router

    这个项目没有使用正则,而是将URL按照"/"切割然后保存成为树形结构。

    映射路由的时候,相当于对树进行遍历,复杂度为 O (log n)。

    项目是PHP实现的,不过代码很少。应该很容易看明白的。

    回复
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-18 09:50:46

    为什么不能维护一个路由Dict。值是key对应的func

    回复
    0
  • 黄舟

    黄舟2017-04-18 09:50:46

    正则在路由这块展示的灵活性是其他技术很难替代的。一样用正则,也可以把性能优化,原理很简单,合并正则,通过某种策略来依据正则匹配的结果来判断哪个

    比如有

    • /user/{pid}/profile

    • /news

    • /product/{pid}

    • /product/{pid}/comment/{cid}

    四个路由

    用一个正则 #^(?|/user/(d+)/profile|/news|/product/(d+)()|/product/(d+)/comment/(d+)())$# 匹配#^(?|/user/(d+)/profile|/news|/product/(d+)()|/product/(d+)/comment/(d+)())$# 匹配

    当捕获结果分别有 1,0,2,3个组的时候,我们就知道分别匹配到了第1~4个路由。通过一些代码自动合并正则、分配捕获组数量=>路由的映射,就可以把多个正则合并到一起一次匹配

    这里有个技巧是用(?|)

    当捕获结果分别有 1,0,2,3个组的时候,我们就知道分别匹配到了第1~4个路由。通过一些代码自动合并正则、分配捕获组数量=>路由的映射,就可以把多个正则合并到一起一次匹配

    这里有个技巧是用(?|)来重置捕获组🎜 🎜参考 http://nikic.github.io/2014/0...🎜

    回复
    0
  • 取消回复