Dynamic routing: Gin vs SpringMVC

 Two days in contact with Gin, its dynamic routing interested, specially made notes, with SpringMVC the way for the next comparison.

1 Introduction

 Gin is the use of HTTP Web framework Go / golang language. The interface is simple and extremely high performance. As of version 1.4.0, contains the test code, only 14K, which test code about 9K, source framework that is only about 5K. SpringMVC without much introduction, Java market leaders.

 Gin support dynamic routing, the following simple example:

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 Comparative examples are:

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloWorldController {


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

}
复制代码

Both have similarities.

2.Gin

 Gin Trie tree using dynamic routing. Trie tree, that is, the dictionary tree, also known as the key tree or trie is a tree structure, a variation on the hash tree. Typical applications for statistical and sort a large number of strings (strings, but not limited to), it is often used for text search engine system word frequency statistics. Its advantages are: string comparison minimizing unnecessary, high efficiency Bi Haxi query table.

 Trie core idea is space for time. Use common prefix string to reduce the cost of the query time to achieve greater efficiency. It has three basic properties:

  1. The root node does not include characters, each node except the root node contains only one character.
  2. From the root node to a node on the path through the connected characters, the string corresponding to that node.
  3. All the characters in each node contains child nodes are not the same.

As illustrated, a trie structure holds key 8, "A", "to", "tea", "ted", "ten", "i", "in", "inn". Wherein the bond marked in the node, the value denoted below the node. Each complete English word corresponds to a specific integer. Trie can be seen as a deterministic finite automaton, although generally the edge of the symbol in the sequence is implicit in the branch.

 Trie number of common scenarios include:

  1. String retrieval
  2. Word frequency statistics
  3. Prefix retrieval
  4. Prefix word frequency statistics
  5. Ordering all the strings in lexicographic order

 Gin routing implementation is also similar with the example above, the specific implementation in tree.go file, including the building and the search process trie tree.

2.1. Process achievements

 Look at the node definition

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

Contribution process mainly done by the two methods

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

// 主要用于处理新节点的插入
func (n *node) insertChild(numParams uint8, path string, fullPath string, handlers HandlersChain) {}
复制代码

Process is as follows:
1

Use addRoute method to add a new path P from the root node, if the tree is empty, then directly inserted as a new node, then the node is a first node (root) of the tree, path and fullPath values ​​are P. If there is a sub root node, then find the root path P with a common prefix, if common prefix, then there is no new node is added as a child of the root node, using insertChild method. If there is a common prefix, the split of the current node, the root node (current node) common prefix content independently a child node, and linked to the current node, the update indices; then obtaining a first common prefix character P is removed, the current node indices to determine whether there is a list of the same character that the rest of the content is judged to be added as a new node, or to continue to divide, if you need to continue to divide, addRoute method is repeated.

 The following code as an example,

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 tree is constructed:

2

It should be noted that, for the wild card,: xxxx or *, will appear as a separate node.

2.2. Find procedure

Find the process is relatively simple and straightforward look down from the root node, know where to find matching nodes, as follows:
3

3.SpringMVC

 A simple example is as follows:

@RestController
public class HelloWorldController {

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

}
复制代码

 Before introducing "SpringMVC loading process" is mentioned, Spring MVC routing load is handled by the RequestMappingHandlerMapping. Such annotations will look on all eligible Method, and then added to the parent AbstractHandlerMethodMapping MappingRegistry cache is encapsulated HandlerMethod, direct manner to the HashMap. In addition there are other outside RequestMappingHandlerMapping HandlerMapping, such SimpleUrlHandlerMapping, BeanNameUrlHandlerMapping like.

 When looking HandlerMethod matching HandlerMapping will traverse all, if a HandlerMapping capable of processing, returns a corresponding HandlerExecutionChain, and exit the loop, performed by a specific HandlerAdapter Method, Apdater will complete the implantation parameters. The dynamic routing RequestMappingHandler is reflected in the look of HandlerMethod, the main function is implemented by lookupHandlerMethod method of AbstractHandlerMethodMapping. lookupHandlerMethod method will traverse all the objects registered in MappingRegistry, judged by getMatchingCondition PatternsRequestCondition, specifically referred to AntPathMatcher to achieve.

 AntPathMatcher mainly used for string matching based URLs, matching rules may be as follows:

  • ? Matches one character
  • * Matches zero or more characters
  • ** matches zero or more directories

Embodied in doMatch process.

That is SpringMVC by traversing all registered Url, for each application AntPathMatcher Url determines whether the current registration request Url wildcard written to find the corresponding handler.

The following is a simple diagram:

4

4. Reference

zh.wikipedia.org/wiki/Trie



Guess you like

Origin juejin.im/post/5e6ec64551882549112b55b3