2013-08-16 30 views
4

这个问题已经被问这里:我可以使用什么java库来比较两个URL是否相等?

,但我对这个答案完全不满意。我需要一种方法来比较两个URL是否相等,最好是我不会用手写。这个库需要明白,这些URL相等

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

https://stackoverflow.com/questions/ask 
https://stackoverflow.com/questions/ask/ 

http://stackoverflow.com?paramName= 
http://stackoverflow.com?paramName 

http://stackoverflow.com?paramName1=value1&paramName2=value2 
http://stackoverflow.com?paramName2=value2&paramName1=value1 

http://stackoverflow.com?param name 1=value 1 
http://stackoverflow.com?param%20name%201=value%201 

这些URL是不相等的:

https://stackoverflow.com/questions/ask 
https://stackoverflow.com/questionz/ask 

http://stackoverflow.com?paramName1=value1&paramName2=value2 
http://stackoverflow.com?paramName1=value1&paramName2=value3 

和其他类似这样复杂的事情。我在哪里可以找到这样的图书馆?

顺便说一句,这里就是一个单元测试:

import org.junit.Test; 

import java.net.URI; 
import java.net.URISyntaxException; 

import static org.junit.Assert.assertEquals; 
import static org.junit.Assert.assertNotSame; 

public class UriTest { 

    @Test 
    public void equality() throws URISyntaxException { 
     assertUrlsEqual("http://stackoverflow.com", "https://stackoverflow.com/"); 
     assertUrlsEqual("https://stackoverflow.com/questions/ask", "https://stackoverflow.com/questions/ask/"); 
     assertUrlsEqual("http://stackoverflow.com?paramName=", "http://stackoverflow.com?paramName"); 
     assertUrlsEqual("http://stackoverflow.com?paramName1=value1&paramName2=value2", "http://stackoverflow.com?paramName2=value2&paramName1=value1"); 
     assertUrlsEqual("http://stackoverflow.com?param name 1=value 1", "http://stackoverflow.com?param%20name%201=value%201"); 
    } 

    @Test 
    public void notEqual() throws URISyntaxException { 
     assertUrlsNotEqual("https://stackoverflow.com/questions/ask", "https://stackoverflow.com/questionz/ask"); 
     assertUrlsNotEqual("http://stackoverflow.com?paramName1=value1&paramName2=value2", "http://stackoverflow.com?paramName1=value1&paramName2=value3"); 
    } 

    private void assertUrlsNotEqual(String u1, String u2) throws URISyntaxException { 

//...? 
    } 

    private void assertUrlsEqual(String u1, String u2) throws URISyntaxException { 
//...? 
    } 

} 
+0

看来你只是想看看基地址是否相同,你为什么不尝试在你的URL上调用'getHost()'并且看看它是否等于另一个'URL'? –

+4

'stackoverflow.com'和'stackoverflow.com /'真*不符合规范。他们只是碰巧等同于你的目的。这就是为什么你的要求不是公共库的东西。 –

+0

@JoshM看我的编辑 –

回答

7

java.net.URI会比较两个网址,而无需网络请求(the way java.net.URL does),并且可以使用normalize方法做一个URL绝对路径路径 - 典范。

有一些问题,你的例子:

http://stackoverflow.com?paramName= 
http://stackoverflow.com?paramName 

http://stackoverflow.com?paramName1=value1&paramName2=value2 
http://stackoverflow.com?paramName2=value2&paramName1=value1 

允许服务器分配意义的参数的顺序,以及的存在等号,所以那些对不等价根据RFC 3986

http://stackoverflow.com?param name 1=value 1 
http://stackoverflow.com?param%20name%201=value%201 

并非所有的URL库,要处理这些是有效的,因为首先是未按照RFC 3986的有效URL,尽管大多数用户代理如何将前者转换成一致后者。

+2

好的谢谢你的信息。但是通过在URI上使用'normalize()',我所有的“平等”测试仍然失败,主要是出于您给出的原因。有规范,然后就是现实。现实情况是,大多数服务器将返回相同的东西给予那些“平等”的网址。这就是我想测试的内容,但是这个答案(尽管非常翔实)并不能帮助我达到这个目标。 –

+1

@tieTYT,我同情你的沮丧,但是浏览器之外没有很多代码需要*几乎是URL *并强制它成为一个真实的URL,并且浏览器不太可能试图确定两个URL是否可能仅基于文本分析来引用相同的资源。我知道你不想推出自己的产品,但除非搜索到“启发式”或“模糊”的URL匹配工作,否则你可能倒霉。 [HTML5 2.6](http://dev.w3.org/html5/spec-LC/urls.html#parsing-urls)第2部分的语法扩展可能为* almost * URL提供了一个很好的定义。 –

相关问题