easyui tree动态加载_动态路由:Gin vs SpringMVC

 这两天在接触Gin,对它的动态路由功能比较感兴趣,特意做了笔记,顺便跟SpringMVC作下对比。

1.简介

 Gin是使用Go/golang语言实现的HTTP Web框架。接口简洁,性能极高。截止1.4.0版本,包含测试代码,仅14K,其中测试代码9K左右,也就是说框架源码仅5K左右。SpringMVC不用过多介绍,Java市场的一把手。

 Gin支持动态路由,简单示例如下:

import (    "github.com/gin-gonic/gin"    "net/http")func main() {    r := gin.Default()    r.GET("/hello/:name", func(context *gin.Context) {        context.String(http.StatusOK, "Hello : "+context.Param("name"))    })    r.Run()}

对比SpringMVC的例子为:

import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class HelloWorldController {    @RequestMapping("/hello/{name}")    public String antUser (@PathVariable("name") String name) {        return "Hello : " + name;    }}

二者有相似的地方。

2.Gin

 Gin使用Trie树来实现动态路由。Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。

 Trie的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。它有3个基本性质:

  1. 根节点不包含字符,除根节点外每一个节点都只包含一个字符。
  2. 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
  3. 每个节点的所有子节点包含的字符都不相同。
b221cececf2e5b3b1b27a5e5ac2424c0.png

如上图示,为一个保存了8个键的trie结构,"A", "to", "tea", "ted", "ten", "i", "in", "inn"。其中,键标注在节点中,值标注在节点之下。每一个完整的英文单词对应一个特定的整数。Trie可以看作是一个确定有限状态自动机,尽管边上的符号一般是隐含在分支的顺序中的。

 Trie数的常见应用场景包括:

  1. 字符串检索
  2. 词频统计
  3. 前缀检索
  4. 前缀词频统计
  5. 对所有的字符串按照字典序排序

 Gin的路由实现也是跟上面的例子类似,具体实现在tree.go文件里,主要包括trie树的构建和查找过程。

2.1. 建树过程

 先看node的定义

type node struct {    path      string           // 当前节点相对路径,即公共前缀    indices   string           // 所有孩子节点的path[0]组成的字符串,如果子节点有通配符,则为空    children  []*node          // 孩子节点    handlers  HandlersChain    // 当前节点的处理函数(包括中间件)    priority  uint32           // 当前节点及子孙节点的实际路由数量    nType     nodeType         // 节点类型    maxParams uint8            // 子孙节点的最大参数数量    wildChild bool             // 孩子节点是否有通配符(wildcard)    fullPath  string           // 完整的请求路径,各中间节点也有}

建树过程主要由两个方法来完成

// 根据给定的路径增加一个节点,主要用于处理公共前缀的分割func (n *node) addRoute(path string, handlers HandlersChain) {}// 主要用于处理新节点的插入func (n *node) insertChild(numParams uint8, path string, fullPath string, handlers HandlersChain) {}

流程如下:

95964937d917158a74698b2895e42526.png

使用addRoute方法从根节点添加一个新的路径P,如果树为空,则作为新节点直接插入,此时该节点为树中的第一个节点(根节点),path和fullPath值都为P。如果根节点存在子节点,则找到P跟根节点path的公共前缀,如果不存在公共前缀,则将新节点作为根节点的子节点加入,使用insertChild方法。如果存在公共前缀,则分裂当前节点,将根节点(当前节点)公共前缀后的内容独立为一个子节点,并挂到当前节点下,更新indices;接着获取P去掉公共前缀的第一个字符,判断当前节点indices列表是否存在相同的字符,即判断剩下的内容是要作为新节点加入,还是要继续分裂,如果需要继续分裂,则重复addRoute方法。

 以下面这段代码为例,

r.GET("/q/query", func(context *gin.Context) {    context.String(http.StatusOK,"Hello "+context.Query("name"))})r.GET("/q/qaz/:name", func(context *gin.Context) {    context.String(http.StatusOK,"Hello "+context.Query("name"))})r.GET("/q/qaj/:name/l", func(context *gin.Context) {    context.String(http.StatusOK,"Hello "+context.Query("name"))})

构建的trie树为:

2.png

a6864b2060b3c9fe65bf222861ac8b13.png

这里需要指出的是,对于通配符,:xxxx或者*,会作为一个单独的节点出现。

2.2. 查找过程

查找过程比较简单,直接从根节点往下找,知道找到匹配的节点,过程如下:

32a385d60051f49f1e7256a3585f3626.png
3.SpringMVC

 如下为一个简单的示例:

@RestControllerpublic class HelloWorldController {    @RequestMapping("/hello/{name}")    public String antUser (@PathVariable("name") String name) {        return "hello : " + name;    }}

 之前在介绍《SpringMVC加载流程》是说过,Spring MVC路由的加载是由RequestMappingHandlerMapping来处理的。该类会查找所有符合条件的Method上的注解,然后添加到父类AbstractHandlerMethodMapping的MappingRegistry中封装为HandlerMethod进行缓存,直接以HashMap的方式。除了RequestMappingHandlerMapping外还有其他HandlerMapping,如SimpleUrlHandlerMapping,BeanNameUrlHandlerMapping等。

 当查找符合的HandlerMethod时会遍历所有的HandlerMapping,如果某HandlerMapping能够处理,返回对应的HandlerExecutionChain,同时退出循环,由HandlerAdapter来执行具体的Method,Apdater会完成入参的注入。而RequestMappingHandler的动态路由则体现在HandlerMethod的查找上,该功能主要由AbstractHandlerMethodMapping的lookupHandlerMethod方法来实现。lookupHandlerMethod方法会遍历MappingRegistry中的所有注册对象,通过PatternsRequestCondition的getMatchingCondition来判断,具体交由AntPathMatcher来实现。

 AntPathMatcher主要用来做类URLs字符串匹配,可以匹配的规则如下:

  • ?匹配一个字符
  • *匹配0个或多个字符
  • **匹配0个或多个目录

具体实现在doMatch方法中。

即SpringMVC是通过遍历所有注册的Url,对每个Url应用AntPathMatcher来判断当前请求的Url是否符合注册的通配符写法,从而找到对应的处理函数。

如下为简单的示意图:

918359ac8c06ee55c9ed7d458ea7ff2a.png
4.参考

https://zh.wikipedia.org/wiki/Trie

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/574751.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

伍德里奇---计量经济学第6章部分计算机习题详解(stata),伍德里奇---计量经济学第6章部分计算机习题详解(STATA)...

所以,log bwg t7.5840.0180npvis?0.00041npvis20.0254mage?0.00041mage20.1370.00370.000120.0093 (0.00015)n1764,R20.0256,R20.0234。当孩子的出生体重最大时,对应的年龄为mage? β12β20.0254[2?0.00041] 30.96&#xff0c…

vue菜单点击html,基于vue.js实现侧边菜单栏

侧边菜单栏应该是很多项目里必不可少的 自己手写了一个下面是效果图下面就说一下实现的过程 还是比较简单的首先导入一下需要的文件接下来就是我的html主页系统用户管理权限设置操作日志设备运行日志防区 防区管理警报 历史报警曲线报表统计警情处理设备然后是css* {margin: 0;…

centos7 mysql启动失败_Mysql主从复制

​好在,别人如何分析我,跟我本身是一点关系也没有的。(by 三毛)主从复制的常见用途1.数据备份对备份来说,复制是一项很有意义的技术补充,但复制既不是备份也不能取代备份2.负载均衡(读写分离)通过MySQL主从复制,可以把写操作放在主库(master)&#xff0c…

计算机应用基础知道,谁知道计算机应用基础练习题的答案?

谁知道计算机应用基础练习题的答案?46.简述美籍匈牙利数学家冯诺依曼(Von Neumann)在1946年提出的关于计算机的体系结构和“程序存储”的设计思想。47.简要说明Windows98中安装存放在CD—ROM上的应用程序的操作过程。48.简述Windo…

计算机程序编辑器中文版,小说编辑器(Atomic Scribbler)

AtomicScribbler是一款功能强大的电脑小说编辑器,快速编辑、创作你的小说,也可以直接导入文本二次编辑,内置了丰富的文字编辑工具,完全能够满足日常创作小说、编辑文字使用需求。。相关软件软件大小版本说明下载地址AtomicScribbl…

信号与系统sa函数求积分_瞎扯数学分析微积分(1~4)

算法数学之美日期:2019年10月30日正文共:12013字0图预计阅读时间:31分钟来源:豆瓣 wxmang这一篇帖子主要介绍人类如何从一个基于几何直观或直觉的计算技巧或计算方法,进化到逻辑基础严密的公理体系的例子,想说明人类抽…

Cocos2D研究院之CCNode详解(三)

http://www.xuanyusong.com/archives/950 上一章我们了解了cocos2d的项目路径以及工作原理,这次作者要真刀真枪地讲解代码了,咱们先来看看cocos2d最常用、也是作者认为最核心的类——CCNode。 之前说过,cocos2d的所有类都以CC开头&#xff0c…

计算机第二课堂教学计划,小学的第二课堂教学计划

小学的第二课堂教学计划开展内容丰富,形式多样的第二课堂活动,通过活动,使学生受到爱国主义及道德情感教育,掌握技能,全面提高他们的素质,使其成为全面发展的一代新人。下面是小编分享给大家的小学的第二课…

webstorm两个文件比对_webstorm怎么更改文件名称?或者是重命名

在开发的过程中,我们一个项目中会有很多的文件,每个文件中也会有很多的层级关系,有时候新建一个文件的时候,一不下心就会出错,位置出错我们可以移动更换位置,名称命名错误,我们可以重命名&#…

秒懂物理计算机出题规划,57张动图, 让你秒懂高中物理原理! 考试次次拿第一

原标题:57张动图, 让你秒懂高中物理原理! 考试次次拿第一物理不像语文或者英语,文科的东西记的东西偏多,理解的成分偏少,但物理理解的成分很重,要死记硬背的东西反而很少。要想把物理学好,先要把简单的概念…

matlab机器人自动分拣_极智嘉分拣系统落地 助力打造智慧物流引擎

全球AMR引领者极智嘉(Geek)近日宣布已为知名跨境电商企业棒谷科技(Banggood)部署全柔性智能AMR分拣系统,以支持棒谷科技日益增长的海外跨境电商业务需求。棒谷科技业务体系遍及全球200多个国家。随着电商业务的加速转变,棒谷科技的发展面临线上销售增长快、业务需求难以预测、劳…

n分频器 verilog_时钟分频系列——分数分频电路的Verilog实现

IC君的第47篇原创文章上一篇文章时钟分频系列——偶数分频/奇数分频/分数分频,IC君介绍了各种分频器的设计原理,其中分数分频器较为复杂,这一篇文章IC君再跟大家聊聊分数分频的具体设计实现。一个分数分频器由两部分组成:以ZN和ZN…

通过gdb调试分析Linux内核的启动过程

作者:吴乐 山东师范大学 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一、实验流程 1.打开环境 执行命令:cd LinuxKernel/ 执行命令:qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img M…

清除服务器上传队列的文件,webUploader上传demo

最近,要做文件上传功能,在同事推荐下,选择了webUploader插件。WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件,详情请看官网(直接百度webUploader,应该是第…

HappyLeetcode64:Sqrt(x)

Implement int sqrt(int x). 这道题本质上是求sqrt(x)下最大的整数。二分查找是比较容易想到的方法。另&#xff0c;在网上又学习了下别人的牛顿迭代法。 这是我原来的写法&#xff0c;写入是错误的&#xff0c;复杂度太高 class Solution { public:int sqrt(int x) {if (x <…

德云斗笑社何九华为什么没参加_狗狗的身体卡在了门上,女主人低头一看忍不住笑了:这是膨胀了...

大家应该有看过长得像煤气罐一样体型圆圆的狗狗吧&#xff1f;它们可能是因为疾病导致的&#xff0c;也可能是被主人喂得过于肥胖了。这个故事中的狗狗被过分宠溺&#xff0c;才短短的几个月&#xff0c;它居然画风突变&#xff0c;不禁想问这是去参加宠物变形记了吗&#xff1…

服务器绑定域名可修改吗,云服务器可以绑定域名吗

云服务器可以绑定域名吗 内容精选换一换访问IIS搭建的网站不通&#xff0c;报错404。IIS上绑定的域名只填写了主机名&#xff0c;没有指定IP地址。本节操作指导用户修改IIS上绑定的域名&#xff0c;以Windows Server 2008 R2操作系统云服务器为例。登录服务器&#xff0c;选择“…

杭州保俶塔实验机器人_【科教有闻】高照实验学校Pepper机器人课程亮相2020(杭州)国际数字教育大会“智能教育引领未来”论坛...

“数化世间万物&#xff0c;一切皆有可能”&#xff0c;数字经济时代的教育新画卷正在浙江杭州徐徐展开。12月10日至11日&#xff0c;2020(杭州)国际数字教育大会(2020iDEE)在杭州国际博览中心正式开幕&#xff0c;这是一场关乎数字和创新的盛宴&#xff0c;也是一次洞见未来教…

hdu2795 Billboard 线段树

题意&#xff1a; 给出一块h*w的广告牌&#xff0c;还有n张1*u的海报&#xff0c;海报尽量往上&#xff0c;左边的位置张贴&#xff0c;问每一张海报能贴的多高。 线段树单点修改。 注意&#xff1a;因为1 < h,w < 10^9; 1 < n < 200,000&#xff0c;但实际上&…

实现iframe_面试官:来说说单点登录的三种实现方式

前言在 B/S 系统中&#xff0c;登录功能通常都是基于 Cookie 来实现的。当用户登录成功后&#xff0c;一般会将登录状态记录到 Session 中&#xff0c;或者是给用户签发一个 Token&#xff0c;无论哪一种方式&#xff0c;都需要在客户端保存一些信息&#xff08;Session ID 或 …