spring url 匹配规则

场景

公司的后端服务采用service mesh做服务治理,网关转发时,通过URL作为唯一标识,找到网关配置中URL对应的应用名,

该应用名就是service mesh中的域名,但是由于一些特殊的URL,例如url中带入参数,这种是不通用的,需要一定的规则匹配,如果某些条件没有考虑到可能导致获取到的应用名并不是目标想访问的,带来一定的错误。

匹配优先级

关于url的匹配优先级定义,阿里云的网关给出了相应的标准规则,阿里云官方文档:路径匹配规则 - SOFAStack API 统一网关 - 阿里云

API 网关支持三种匹配方式。不可避免的,多个 API 之间会出现冲突。比如 /hello 和 /{id} 这两个 API 当遇到路径为 /hello 的请求时,就会冲突。

针对这种冲突情况,API 网关会遵循 最长路径优先 规则。当路径长度相同时,继而遵循 绝对匹配 > 参数匹配 > 前缀匹配 的规则(更详细的说明请参照上面的官方文档)。

*示例,以下配置,优先级由低到高, 为前缀匹配

​​​​​​​​​​​​​GET /*
GET /{id}
GET /path
GET /{id}/*
GET /{id}/{name}
GET /{id}/temp
GET /path/*
GET /path/{id}
GET /path/temp
GET /{id}/{name}/{path}

Spring MVC在代码上对优先级的实现

spring framework util 提供了一个 AntPathMatcher 类,该类用于做url方面的匹配,下面说一下如何使用该类在众多url中找到最匹配的那一个。

  1. 创建该类对象

AntPathMatcher MATCHER = new AntPathMatcher()

  1. 判断一个url是否是特殊url

MATCHER.isPattern(path);

  1. 使用url创建一个对比对象,用于多个与之匹配的url作为一个list进行sort,sort后的第一个就是最匹配的

Comparator comparator = MATCHER.getPatternComparator(path);

完整代码

    /**
     * 找到匹配的url
     * @param paths 所有match url
     * @param path 需要匹配的url
     * @return
     */
    public static String getStrategyForPath(List<String> paths, String path) {
    
    
        // 先找到匹配的url
        List<String> matchingPatterns = new ArrayList<>();
        for (String pattern : paths) {
    
    
            // 判断该url是否与目标匹配,匹配的话加入到list
            if (MATCHER.match(pattern, path)) {
    
    
                matchingPatterns.add(pattern);
            }
        }
        // 从匹配的url中选取一个最合适的
        if (!matchingPatterns.isEmpty()) {
    
    
            Comparator<String> comparator = MATCHER.getPatternComparator(path);
            // 进行排序
            matchingPatterns.sort(comparator);
            // 拿到第一个最匹配的
            return matchingPatterns.get(0);
        }
        return null;
    }

上面这段代码基本照搬了Spring core中的源码,Spring MVC中对url的优先级匹配也是这么做的:
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43861630/article/details/131163378