如何比较java中的两个URL?

这是一个简单的问题 – 给定两个url,是否有一些内置方法,或者一个Apache库来决定它们(逻辑上)是否相等?

例如,这两个url是相同的:

http://stackoverflow.com http://stackoverflow.com/ 

虽然URI.equals() (以及有问题的URL.equals() )对于这些特定示例并不返回true ,但我认为这是唯一可以假设等价的情况(因为HTTP协议中没有空路径) 。

不能假定URI http://stackoverflow.com/foohttp://stackoverflow.com/foo/是等效的。

也许你可以使用URI.equals()包装在一个显式处理这个特定情况的实用程序方法中。

URL ::等于引用

 URL urlOne = new URL("http://stackoverflow.com"); URL urlTwo = new URL("http://stackoverflow.com/"); if( urlOne.equals(urlTwo) ) { // .... } 

来自文档的说明 –

如果两个URL对象具有相同的协议,引用等效主机,主机上具有相同的端口号,以及文件的相同文件和片段,则它们是相等的。

如果两个主机名都可以解析为相同的IP地址,则认为两个主机是等效的。 否则,如果无法解析任何一个主机名,则主机名必须相等而不考虑大小写; 或两个主机名都等于​​null。

由于主机比较需要名称解析,因此此操作是阻止操作。

注意:已知已定义的equals行为与HTTP中的虚拟主机不一致。

所以,你应该更喜欢@Joachim建议的URI :: equals引用 。

以下内容可能适用于您 – 它validation2个URL是相等的,允许以不同的顺序提供参数,并允许配置各种选项,即:

  • 主机是否区分大小写
  • 路径是否区分大小写
  • 查询字符串参数区分大小写
  • 查询字符串值是否区分大小写
  • 该方案是否区分大小写

您可以像这样测试它:

 class Main { public static void main(String[] args) { UrlComparer urlComparer = new UrlComparer(); expectResult(false, "key a case different", urlComparer.urlsMatch("//test.com?A=a&B=b", "//test.com?a=a&b=b")); expectResult(false, "key a case different", urlComparer.urlsMatch("https://WWW.TEST.COM?A=1&b=2", "https://www.test.com?b=2&a=1")); expectResult(false, "key a value different", urlComparer.urlsMatch("/test?a=2&A=A", "/test?a=A&a=2")); expectResult(false, "key a value different", urlComparer.urlsMatch("https://WWW.TEST.COM?A=a&b=2", "https://www.test.com?b=2&A=1")); expectResult(false, "null", urlComparer.urlsMatch("/test", null)); expectResult(false, "null", urlComparer.urlsMatch(null, "/test")); expectResult(false, "port different", urlComparer.urlsMatch("//test.com:22?A=a&B=b", "//test.com:443?A=a&B=b")); expectResult(false, "port different", urlComparer.urlsMatch("https://WWW.TEST.COM:8443", "https://www.test.com")); expectResult(false, "protocol different", urlComparer.urlsMatch("http://WWW.TEST.COM:2121", "https://www.test.com:2121")); expectResult(false, "protocol different", urlComparer.urlsMatch("http://WWW.TEST.COM?A=a&b=2", "https://www.test.com?b=2&A=a")); expectResult(true, "both null", urlComparer.urlsMatch(null, null)); expectResult(true, "host and scheme different case", urlComparer.urlsMatch("HTTPS://WWW.TEST.COM", "https://www.test.com")); expectResult(true, "host different case", urlComparer.urlsMatch("https://WWW.TEST.COM:443", "https://www.test.com")); expectResult(true, "identical urls", urlComparer.urlsMatch("//test.com:443?A=a&B=b", "//test.com:443?A=a&B=b")); expectResult(true, "identical urls", urlComparer.urlsMatch("/test?a=A&a=2", "/test?a=A&a=2")); expectResult(true, "identical urls", urlComparer.urlsMatch("https://www.test.com", "https://www.test.com")); expectResult(true, "parameter order changed", urlComparer.urlsMatch("https://www.test.com?a=1&b=2&c=522%2fMe", "https://www.test.com?c=522%2fMe&b=2&a=1")); expectResult(true, "parmeter order changed", urlComparer.urlsMatch("https://WWW.TEST.COM?a=1&b=2", "https://www.test.com?b=2&a=1")); } public static void expectResult(boolean expectedResult, String msg, boolean result) { if (expectedResult != result) throw new RuntimeException(msg); } } 

UrlComparer.java

 import java.net.URI; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.TreeMap; import org.apache.http.NameValuePair; import org.apache.http.client.utils.URLEncodedUtils; public class UrlComparer { 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; URI uri1 = new URI(url1); URI uri2 = new URI(url2); // Compare Query String Parameters Map mapParams1 = getQueryStringParams(uri1); Map mapParams2 = getQueryStringParams(uri2); if (!mapsAreEqual(mapParams1, mapParams2, getQueryStringValuesAreCaseSensitive())) return false; // Compare scheme (http or https) if (!stringsAreEqual(uri1.getScheme(), uri2.getScheme(), 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 getQueryStringParams(URI uri) { Map 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 map1, Map map2, boolean caseSensitiveValues) { for (Map.Entry 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 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 getListAsMap(List list, boolean caseSensitiveKeys) { Map result; if (caseSensitiveKeys) { result = new HashMap(); } else { result = new TreeMap(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; } } 

sameFile

public boolean sameFile(URL other)比较两个URL,

排除片段组件。 如果此URL和另一个参数相等而不考虑片段组件,则返回true。

参数:other – 要比较的URL。 返回:如果它们引用同一个远程对象,则返回true; 否则是假的。

也请通过这个链接

http://download.oracle.com/javase/6/docs/api/java/net/URL.html#sameFile(java.net.URL)

由于iam无法添加评论,浏览器抛出Javascript错误。 所以我在这里添加我的评论。 对于不便感到遗憾。

//这就是我所说的

 >URL url1 = new URL("http://stackoverflow.com/foo"); >URL url2 = new URL("http://stackoverflow.com/foo/"); >System.out.println(url1.sameFile(url2)); // this is suggested by Joachim Sauer >URI uri = new URI("http://stackoverflow.com/foo/"); >System.out.println(uri.equals("http://stackoverflow.com/foo")); // Both are giving same result 

所以Joachim Sauer检查一次。