framework1/framework/Tree.go

148 lines
3.2 KiB
Go
Raw Permalink Normal View History

2024-10-16 16:53:09 +08:00
package framework
import (
"errors"
"strings"
)
type Tree struct {
root *node // 根节点
}
func NewTree() *Tree {
root := newNode()
return &Tree{root}
}
type node struct {
isLast bool // 代表这个节点是否可以成为最终的路由规则。该节点是否能成为一个独立的uri, 是否自身就是一个终极节点
segment string // uri中的字符串代表这个节点表示的路由中某个段的字符串
handler ControllerHandler // 代表这个节点中包含的控制器,用于最终加载调用
children []*node // 代表这个节点下的子节点
}
func newNode() *node {
return &node{
isLast: false,
segment: "",
children: []*node{},
}
}
func isWildSegment(segment string) bool {
return strings.HasPrefix(segment, ":")
}
func (n *node) filterChildNodes(segment string) []*node {
if len(n.children) == 0 {
return nil
}
if isWildSegment(segment) {
return n.children
}
nodes := make([]*node, 0, len(n.children))
for _, child := range n.children {
if isWildSegment(child.segment) {
nodes = append(nodes, child)
} else if child.segment == segment {
nodes = append(nodes, child)
}
}
return nodes
}
func (n *node) matchNode(uri string) *node {
segments := strings.SplitN(uri, "/", 2) // 使用分隔符将uri切割为两个部分
segment := segments[0] // 第一个部分用于匹配下一层子节点
if segment == "" {
return n.matchNode(segments[1])
}
if !isWildSegment(segment) {
segment = strings.ToUpper(segment)
}
children := n.filterChildNodes(segment) // 匹配符合的下一层子节点
if children == nil || len(children) == 0 {
return nil
}
if len(segments) == 1 {
// 如果segment已经是最后一个节点判断这些children是否有isLast标志
for _, tn := range children {
if tn.isLast {
return tn
}
}
return nil
}
// 如果有2个segment, 递归每个子节点继续进行查找
for _, child := range children {
tnMatch := child.matchNode(segments[1])
if tnMatch != nil {
return tnMatch
}
}
return nil
}
func (tree *Tree) AddRouter(uri string, handler ControllerHandler) error {
n := tree.root
// 确认路由是否冲突
if n.matchNode(uri) != nil {
return errors.New("route exist: " + uri)
}
segments := strings.Split(uri, "/")
for index, segment := range segments {
if segment == "" {
continue
}
if !isWildSegment(segment) {
segment = strings.ToUpper(segment)
}
isLast := index == len(segments)-1
var objNode *node // 标记是否有合适的子节点
children := n.filterChildNodes(segment)
if len(children) > 0 {
// 如果有segment相同的子节点则选择这个子节点
for _, child := range children {
if child.segment == segment {
objNode = child
break
}
}
}
//如果没有找到合适的子节点就要创建一个新节点
if objNode == nil {
child := &node{}
child.segment = segment
if isLast {
child.isLast = true
child.handler = handler
}
n.children = append(n.children, child)
objNode = child
}
n = objNode
}
return nil
}
func (tree *Tree) FindHandler(uri string) ControllerHandler {
match := tree.root.matchNode(uri)
if match == nil {
return nil
}
return match.handler
}