数据结构与算法,url安全验证,路由前缀树

系统url(路由验证),路由前缀树初代目

前段时间学习完算法与数据结构,经过了一段时间的经验总结,把以前写的第一套路由前缀树拿出了看看,

第一版有很多的不足,以及无法使用,仅供学术参考。不要在项目中使用!!

阅读该文章需要一定的算法基础,且我只是普通的开发程序员,并非算法岗职务,并不具有专业性

    private final static Node NODE = new Node();

    private static class Node {
        int end;
        HashMap<String, Node> map = new HashMap<>();

        private Node() {
            end = 0;
        }
    }

简单说一下思路,node在系统启动时,将白名单或黑名单,加载进入node对象中。end作为是否有此结束标识,里层map代表其他树枝。

抽象逻辑概念图
图1
组成简易的抽象树形结构,如果bbb在名单中,则bbb上的end大于1,继续上代码

// 构建树方法,如果遇到没有的地方就创建分支,生成一颗完整的树
public static void insert(String url) {
        if (url == null || url.length() < 2) {
            return;
        }
        // 切分url 如 aa/bb/cc
        // 变成['aa','bb','cc']
        // aa/bb/cc.pdf为['aa','bb','cc.pdf']
        String[] s = url.split("/");
        // 拿出最后一项 cc.pdf
        String e = s[s.length - 1];
        Node n = NODE;
        for (String u : s) {
        	// 截取第一个为空串,略过即可
            if ("".equals(u)) {
                continue;
            }
            // 判断下是否为最后一项
            if (u.equals(e)) {
                String[] h;
                // 切点判断,在判断中,默认 ( . ) 一定为最后一项,将点前后分别生成树枝
                // 主要是针对 **.pdf、**.png等等 请求路由不考虑其他乱序情况
                // 如果不是,则继续向后执行
                if ((h = u.split("\\.")).length > 1) {
                    if (h.length > 2) {
                        return;
                    }
                    // 根据插入值,生成树
                    if (n.map.get(h[0]) == null) {
                        n.map.put(h[0], new Node());
                    }
                    // 每一次等号复制的含义就像盖楼,每一次赋值就是前进一层
                    n = n.map.get(h[0]);
                    n.map.put(h[1], new Node());
                    n = n.map.get(h[1]);
                    n.end++;
                    // 上面四行代码 比如url: aa.pdf
                    // 结合更上面判空,如果aa不存在,构建aa树枝
                    // 踩到aa上面,生成pdf树枝
                    // 标记pdf树枝处有一个结束点
                    return;
                }
            }
            // 这里不是最后一个  比如 : aa/bb/cc.pdf
           // 这里是aa 或者bb
           // 当前不存在,创建该树枝
            if (n.map.get(u) == null) {
                n.map.put(u, new Node());
            }
            // 爬到该树枝之上
            n = n.map.get(u);

        }
        n.end++;
    }

接下来就是使用该树验证url

    public static boolean isMatch(String url) {
    	// 默认不存在过短的url 小众情况不考虑
        if (url == null || url.length() < 2) {
            return false;
        }
        // 该处与上面同理
        String[] s = url.split("/");
        String e = s[s.length - 1];
        Node n = NODE;
        for (String u : s) {
        // 传统艺能 空串略过
            if ("".equals(u)) {
                continue;
            }
            
            if (n.map.get(u) == null) {
				// 该处同理找到最后一个
                if (u.equals(e)) {
                    String[] h;
                    if ((h = u.split("\\.")).length > 1) {
                        if (h.length == 2) {
                        	//最后的判断单独判断
                            return judgeEnding(h, n);
                        }
                    }
                }
				// 遇到通配符 爬到通配符树枝上
                if (n.map.get("*") != null) {
                    n = n.map.get("*");
                    continue;
                }
                // 遇到双*通配符 结束判断是否符合
                if (n.map.get("**") != null) {
                    n = n.map.get("**");
                    break;
                }
                return false;
            } else {
            // 普通的爬树
                n = n.map.get(u);
            }
        }
        // 结束判断 是否有此结束项
        return n.end > 0;
    }

private static boolean judgeEnding(String[] h, Node n) {

        if (n.map.get(h[0]) != null) {
        	// 如 结尾 为 aa.pdf 则爬aa树枝
            n = n.map.get(h[0]);
        } else if (n.map.get("*") != null) {
        	// 没有aa树枝 但是有通配符*树枝,则爬上*树枝
            n = n.map.get("*");
        } else {
        	// 没有树枝 则毁灭吧
            n = null;
        }
		// 在此处 返回 不符合
        if (n == null) {
            return false;
        }
		// 该处为双重判断 为爬 pdf树枝 并且它必须存在 
		// 同时存在该处结尾
		// 同时满足 则符合
        return (n = n.map.get(h[1])) != null && n.end > 0;
    }

end的主要作用,为 中间项url
如 树存在 aa/bb/cc 树枝 但不存在aa/bb
那么url aa/bb 再bb上end为0 不符合返回false

总结

该结构为本人自学数据结构与算法的学术性算法,该结构我明确表示是有问题的,不具备使用价值,在本人工作的项目中并没有引用该代码。

比如通配符url与普通url之间会互相影响,影响判断结果,但是主要是思路的展现与大家交流。

因为工作原因,没有时间一直去完善,但是目前已经完成了第二套更加稳定的路由前缀树算法结构,且目前没有发现问题,会在后续更新中与大家分享。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值