用Java比较两URI是否相同

需求是http和https协议视为相同,且最后带不带/也无所谓,比如http://stackoverflow.com 和 https://stackoverflow.com/ 应视为相同。
JDK现有的api包括URI.equals和URL.equals应该是不符合需求的。

为此从stackoverflow(How to compare two URLs in java?)上找了个别人写的工具类,稍作调整后实现了需求:

import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;

import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;


public class UrlComparer {

  private String HTTP = "http";
  private String HTTPS = "https";

  private boolean hostIsCaseSensitive = false;
  private boolean pathIsCaseSensitive = true;
  private boolean queryStringKeysAreCaseSensitive = true;
  private boolean queryStringValuesAreCaseSensitive = false;
  private boolean schemeIsCaseSensitive = false;

  public boolean urlsMatch(String url1, String url2) {
    try {
      if (Objects.equals(url1, url2)) {
        return true;
      }
      url1 = url1.replaceFirst("/+\\z", ""); //去掉最后的/
      url2 = url2.replaceFirst("/+\\z", "");

      URI uri1 = new URI(url1);
      URI uri2 = new URI(url2);

      // Compare Query String Parameters
      Map<String, String> mapParams1 = getQueryStringParams(uri1);
      Map<String, String> mapParams2 = getQueryStringParams(uri2);
      if (!mapsAreEqual(mapParams1, mapParams2, getQueryStringValuesAreCaseSensitive())) {
        return false;
      }

      // Compare scheme (http equals https)
      String scheme1 = HTTPS.equalsIgnoreCase(uri1.getScheme()) ? HTTP : uri1.getScheme();
      String scheme2 = HTTPS.equalsIgnoreCase(uri2.getScheme()) ? HTTP : uri2.getScheme();
      if (!stringsAreEqual(scheme1, scheme2, getSchemeIsCaseSensitive())) {
        return false;
      }

      // Compare host
      if (!stringsAreEqual(uri1.getHost(), uri2.getHost(), getHostIsCaseSensitive())) {
        return false;
      }

      // Compare path
      if (!stringsAreEqual(uri1.getPath(), uri2.getPath(), getPathIsCaseSensitive())) {
        return false;
      }

      // Compare ports
      if (!portsAreEqual(uri1, uri2)) {
        return false;
      }

      return true;
    } catch (Exception e) {
      return false;
    }
  }

  protected Map<String, String> getQueryStringParams(URI uri) {
    Map<String, String> result = getListAsMap(URLEncodedUtils.parse(uri, "UTF-8"),
        getQueryStringKeysAreCaseSensitive());

    return result;
  }

  protected boolean stringsAreEqual(String s1, String s2, boolean caseSensitive) {
    // Eliminate null cases
    if (s1 == null || s2 == null) {
      if (s1 == s2) {
        return true;
      }
      return false;
    }

    if (caseSensitive) {
      return s1.equals(s2);
    }

    return s1.equalsIgnoreCase(s2);
  }

  protected boolean mapsAreEqual(Map<String, String> map1, Map<String, String> map2,
      boolean caseSensitiveValues) {
    for (Map.Entry<String, String> entry : map1.entrySet()) {
      String key = entry.getKey();
      String map1value = entry.getValue();
      String map2value = map2.get(key);

      if (!stringsAreEqual(map1value, map2value, caseSensitiveValues)) {
        return false;
      }
    }
    for (Map.Entry<String, String> entry : map2.entrySet()) {
      String key = entry.getKey();
      String map2value = entry.getValue();
      String map1value = map2.get(key);

      if (!stringsAreEqual(map1value, map2value, caseSensitiveValues)) {
        return false;
      }
    }

    return true;
  }

  protected boolean portsAreEqual(URI uri1, URI uri2) {
    int port1 = uri1.getPort();
    int port2 = uri2.getPort();

    if (port1 == port2) {
      return true;
    }

    if (port1 == -1) {
      String scheme1 = (uri1.getScheme() == null ? "http" : uri1.getScheme()).toLowerCase();
      port1 = scheme1.equals("http") ? 80 : 443;
    }
    if (port2 == -1) {
      String scheme2 = (uri2.getScheme() == null ? "http" : uri2.getScheme()).toLowerCase();
      port2 = scheme2.equals("http") ? 80 : 443;
    }

    boolean result = (port1 == port2);

    return result;
  }

  protected Map<String, String> getListAsMap(List<NameValuePair> list, boolean caseSensitiveKeys) {
    Map<String, String> result;

    if (caseSensitiveKeys) {
      result = new HashMap<String, String>();
    } else {
      result = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
    }

    for (NameValuePair param : list) {
      if (caseSensitiveKeys) {
        if (!result.containsKey(param.getName())) {
          result.put(param.getName(), param.getValue());
        }
      } else {
        result.put(param.getName(), param.getValue());
      }
    }

    return result;
  }

  public boolean getSchemeIsCaseSensitive() {
    return schemeIsCaseSensitive;
  }

  public void setSchemeIsCaseSensitive(boolean schemeIsCaseSensitive) {
    this.schemeIsCaseSensitive = schemeIsCaseSensitive;
  }

  public boolean getHostIsCaseSensitive() {
    return hostIsCaseSensitive;
  }

  public void setHostIsCaseSensitive(boolean hostIsCaseSensitive) {
    this.hostIsCaseSensitive = hostIsCaseSensitive;
  }

  public boolean getPathIsCaseSensitive() {
    return pathIsCaseSensitive;
  }

  public void setPathIsCaseSensitive(boolean pathIsCaseSensitive) {
    this.pathIsCaseSensitive = pathIsCaseSensitive;
  }

  public boolean getQueryStringKeysAreCaseSensitive() {
    return queryStringKeysAreCaseSensitive;
  }

  public void setQueryStringKeysAreCaseSensitive(boolean queryStringKeysAreCaseSensitive) {
    this.queryStringKeysAreCaseSensitive = queryStringKeysAreCaseSensitive;
  }

  public boolean getQueryStringValuesAreCaseSensitive() {
    return queryStringValuesAreCaseSensitive;
  }

  public void setQueryStringValuesAreCaseSensitive(boolean queryStringValuesAreCaseSensitive) {
    this.queryStringValuesAreCaseSensitive = queryStringValuesAreCaseSensitive;
  }

  public static UrlComparer getInstance() {
    return SingletonHolder.INSTANCE;
  }

  private static class SingletonHolder {

    static final UrlComparer INSTANCE = new UrlComparer();
  }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_23204557

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值