URL高效匹配算法如何实现?

项目想通过URL来实现接口鉴权,用户下可以查询到能访问的URL列表,但是URL可能是一个正则表达式,如下所示,某个用户的URL列表,表示用户可以访问
/aa/bb,/aa/cc,和/bb下所有的接口。

/aa/bb
/aa/cc
/bb/**


import lombok.Data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName: TestPath
 * @Description: TODO
 * @Author: wuzhiyong
 * @Time: 2022/2/8 10:57
 * @Version: v1.0
 **/
public class TestPath {
    public static void main(String[] args) {
        List<String> paths = new ArrayList<>();
        paths.add("/a/a/vv/vv/d");
        paths.add("/b/a/ss/vv/d");
        paths.add("/c/b/*/vv/d");
        paths.add("/a/a/vv/ss/d");
        paths.add("/b/a/vv/vv/d");
        paths.add("/c/a/vv/vv/d");
        TreeNode root = generateTree(paths);
        root.print("");
//        long start = System.currentTimeMillis();
//        long n = 100000000;
//        while (n > 0) {
//            isPass(root, "/c/b/vv/vv/d");
//            n--;
//        }
//        System.out.println(100000000 / (System.currentTimeMillis() - start));
    }

    public static boolean isPass(TreeNode root, String path) {
        String[] vars = path.replaceFirst("/", "").split("/");
        TreeNode node = root;
        for (String var : vars) {
            if (node.getChilds().containsKey(var)) {
                node = node.getChilds().get(var);
                continue;
            }
            if (node.getChilds().containsKey("*")) {
                node = node.getChilds().get("*");
                continue;
            }
            return false;
        }
        return true;
    }

    public static TreeNode generateTree(List<String> paths) {
        TreeNode root = new TreeNode();
        for (String path : paths) {
            insertTree(root, path);
        }
        return root;
    }

    public static void insertTree(TreeNode root, String path) {
        String[] vars = path.replaceFirst("/", "").split("/");
        TreeNode node = root;
        for (String tmp : vars) {
            if (!node.getChilds().containsKey(tmp)) {
                TreeNode tmpNode = new TreeNode();
                node.getChilds().put(tmp, tmpNode);

            }
            node = node.getChilds().get(tmp);
        }
    }
}

@Data
class TreeNode {
    private Map<String, TreeNode> childs = new HashMap();

    public void addChild(String key, TreeNode node) {
        this.childs.put(key, node);
    }

    public boolean isExist(String key) {
        return childs.containsKey(key);
    }

    public TreeNode getNode(List<String> keys) {
        TreeNode tmp = this;
        for (String key : keys) {
            tmp = tmp.getChilds().get(key);
        }
        return tmp;
    }

    public void print(String cpt) {
        if (childs.size() == 0) {
            System.out.println(cpt);
        } else {
            for (String key : childs.keySet()) {
                childs.get(key).print(cpt + "/" + key);
            }
        }
    }
}

像spring security它提供了相关注解,实现url级别的鉴权
比如你的/aa/bb 属于aa接口下面的查询分类 ,在设计权限表时,加入分类aa:query
或者/aa/cc 也是属于查询分类,但是某些用户没用这个权限时,此时你就要分类另起个名字了 比如aa:query1,
这样你登陆的时候,直接就将用户的权限写入到用户信息中,到时候url上面写hasPer(aa:query)就行了
你可以模仿这种设计,它查询用户拥有的权限发生在登陆时,登陆以后直接从登陆用户获取相关权限,一般情况下不会有太大的问题