You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中如何正确比较URI?解决参数、大小写等匹配问题

URI匹配优化方案:处理带参数、大小写、末尾斜杠的场景

你当前的直接字符串匹配方案无法应对URI的多种变体(查询参数、域名大小写、末尾斜杠等),核心解决思路是先对URI做标准化处理,再进行匹配,避免手动字符串操作的繁琐和bug。

一、核心思路

将存储的允许URI和输入的请求URI都转换为统一的标准格式:

  • 协议(scheme)统一小写(如HTTPS://→https://)
  • 域名(host)统一小写(如MyUrl.com→myurl.com)
  • 路径(path)统一去除末尾斜杠(如/foo/→/foo,根路径/保留)
  • 忽略查询参数(query)和片段(fragment)

二、代码实现(基于JDK原生API)

1. 编写URI标准化工具方法

用JDK自带的java.net.URI解析URI,避免手动正则处理:

private static String normalizeUri(String uriStr) throws URISyntaxException {
    URI uri = new URI(uriStr);
    
    // 处理协议:统一小写
    String scheme = uri.getScheme().toLowerCase();
    // 处理域名:统一小写
    String host = uri.getHost().toLowerCase();
    // 处理路径:去除末尾斜杠(根路径"/"除外)
    String path = uri.getPath();
    if (path != null && path.length() > 1 && path.endsWith("/")) {
        path = path.substring(0, path.length() - 1);
    }
    
    // 重新构建标准化URI,忽略查询参数和片段
    return new URI(scheme, host, path, null, null).toString();
}

2. 初始化标准化后的允许URI列表

在初始化ALLOWED_URIS时,先对每个配置的URI做标准化:

private static final Map<String, Set<String>> ALLOWED_URIS;

static {
    try {
        ALLOWED_URIS = ImmutableMap.<String, Set<String>>builder()
                .put(normalizeUri("https://myurl.com/foo"), ImmutableSet.of("GET"))
                .put(normalizeUri("https://anotherurl/bar"), ImmutableSet.of("GET"))
                .put(normalizeUri("https://example.com/foo2"), ImmutableSet.of("GET"))
                .build();
    } catch (URISyntaxException e) {
        throw new RuntimeException("初始化允许URI列表失败", e);
    }
}

3. 修改匹配逻辑

对输入的URI先做标准化,再去Map中匹配:

private static boolean isAllowed(final String uri, final String action) {
    try {
        String normalizedInputUri = normalizeUri(uri);
        return ALLOWED_URIS.getOrDefault(normalizedInputUri, emptySet()).contains(action);
    } catch (URISyntaxException e) {
        // 非法URI直接判定为不允许
        return false;
    }
}

三、可选工具类推荐

如果是Spring项目,可以用org.springframework.web.util.UriComponentsBuilder简化标准化逻辑:

import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

private static String normalizeUri(String uriStr) {
    UriComponents components = UriComponentsBuilder.fromUriString(uriStr).build();
    
    String scheme = components.getScheme().toLowerCase();
    String host = components.getHost().toLowerCase();
    String path = components.getPath();
    if (path != null && path.length() > 1 && path.endsWith("/")) {
        path = path.substring(0, path.length() - 1);
    }
    
    return UriComponentsBuilder.newInstance()
            .scheme(scheme)
            .host(host)
            .path(path)
            .build()
            .toUriString();
}

如果使用Guava库,com.google.common.net.Urls类的normalize方法也能处理部分标准化场景,但需注意它的默认行为(比如保留末尾斜杠),可能需要额外调整。

四、注意事项

  • 永远用URI解析库处理,不要手动写正则切割字符串,避免遗漏边缘场景(如带端口的URI、特殊字符路径等)
  • 标准化规则要前后一致:允许列表和输入URI必须用同一套规则处理
  • 对于非法URI(格式错误),直接返回不允许,避免抛出异常影响业务流程

内容的提问来源于stack exchange,提问作者Robert O'Neal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 15:10:59