| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- package framework
- import (
- "errors"
- "strings"
- )
- type Tree struct {
- root *node // 根节点
- }
- func NewTree() *Tree {
- return &Tree{root: newNode()}
- }
- // 增加路由节点
- /*
- /book/list
- /book/:id (冲突)
- /book/:id/name
- /book/:student/age
- /:user/name
- /:user/name/:age(冲突)
- */
- func (tree *Tree) AddRouter(uri string, handler ControllerHandler) error {
- n := tree.root
- // 确认路由是否冲突
- if n.matchNode(uri) != nil {
- return errors.New("route exists: " + uri)
- }
- segments := strings.Split(uri, "/")
- for index, segment := range segments {
- if !isWildSegment(segment) {
- segment = strings.ToUpper(segment)
- }
- isLast := index == len(segments)-1
- var objNode *node
- childNodes := n.filterChildNodes(segment)
- // 如果有匹配的子节点
- if len(childNodes) > 0 {
- // 如果有segment 相同的子节点,则选择这个子节点
- for _, cNode := range childNodes {
- if cNode.segment == segment {
- objNode = cNode
- break
- }
- }
- }
- if objNode == nil {
- // 创建一个当前 node 的节点
- cnode := newNode()
- cnode.segment = segment
- if isLast {
- cnode.isLast = true
- cnode.handler = handler
- }
- n.childes = append(n.childes, cnode)
- objNode = cnode
- }
- n = objNode
- }
- return nil
- }
- func (tree *Tree) FindHandler(uri string) ControllerHandler {
- matchNode := tree.root.matchNode(uri)
- if matchNode == nil {
- return nil
- }
- return matchNode.handler
- }
- // =====================================================================================================================
- // 代表节点
- type node struct {
- isLast bool // 代表这个节点是否可以成为最终的路由规则。该节点是否能成为一个独立的uri, 是否自身就是一个终极节点
- segment string // uri 中的字符串,代表这个节点表示的路由中某个段的字符串
- handler ControllerHandler // 代表这个节点中包含的控制器,用于最终加载调用
- childes []*node // 代表这个节点下的子节点
- }
- // ---------------------------------------------------------------------------------------------------------------------
- func newNode() *node {
- return &node{
- isLast: false,
- segment: "",
- handler: nil,
- childes: nil,
- }
- }
- // 判断路由是否在节点的所有子节点树中存在了
- func (n *node) matchNode(uri string) *node {
- // 使用分隔符将uri 切割为两部分
- segments := strings.SplitN(uri, "/", 2)
- // 第一个部分用于匹配下一层子节点
- segment := segments[0]
- if !isWildSegment(segment) {
- segment = strings.ToUpper(segment)
- }
- // 匹配符合的下一层子节点
- cNodes := n.filterChildNodes(segment)
- if cNodes == nil || len(cNodes) == 0 {
- // 如果当前子节点没有一个符合,那么说明这个 uri 一定是之前不存在,直接返回 nil
- return nil
- }
- // 如果只有一个segment, 则是最后一个标记
- if len(segments) == 1 {
- // 如果segment 已经是最后一个节点,判断这些 cnode 是否有 isLast 标志
- for _, tn := range cNodes {
- if tn.isLast {
- return tn
- }
- }
- // 都不是最后一个节点
- return nil
- }
- // 如果有 2 个 segment, 递归每个子节点继续进行查找
- for _, tn := range cNodes {
- tnMatch := tn.matchNode(segments[1])
- if tnMatch != nil {
- return tnMatch
- }
- }
- return nil
- }
- // 过滤下一层满足 segment 规则的子节点
- func (n *node) filterChildNodes(segment string) []*node {
- if len(n.childes) == 0 {
- return nil
- }
- // 如果 segment 是通配符,则所有下一层子节点都满足需求
- if isWildSegment(segment) {
- return n.childes
- }
- nodes := make([]*node, 0, len(n.childes))
- // 过滤所有的下一层子节点
- for _, cNode := range n.childes {
- if isWildSegment(cNode.segment) {
- // 如果下一层子节点有通配符,则满足需求
- nodes = append(nodes, cNode)
- } else if cNode.segment == segment {
- // 如果下一层子节点没有通配符,但文本完全匹配,则满足需求
- nodes = append(nodes, cNode)
- }
- }
- return nodes
- }
- // 判断一个 segment 是否是通用 segment, 即以 :开头
- func isWildSegment(segment string) bool {
- return strings.HasPrefix(segment, ":")
- }
|