Java URI.resolve

27

我正在尝试解析两个URI,但这并不像我希望的那样直截了当。

URI a = new URI("http://www.foo.com");
URI b = new URI("bar.html");

问题在于 a.resolve(b).toString() 现在是 "http://www.foo.combar.html"。我该怎么解决这个问题?


你期望的输出结果是什么? - Anthony Forloney
1
"http://www.foo.com/bar.html" 就可以了。 - Cpa
为什么您要使用两个URI?一定有原因,但不太清楚。 - James P.
@JamesP。你原本期望他使用什么? - Ian Boyd
5个回答

35

看起来你可能想使用URL而不是URI(URI更为通用,需要处理语法上不那么严格的情况)。

URI a = new URI("http://www.foo.com");
URI b = new URI("bar.html");
URI c = a.resolve(b);
c.toString()     -> "http://www.foo.combar.html"
c.getAuthority() -> "www.foo.com"
c.getPath()      -> "bar.html"

URI的toString()方法的行为并不像你期望的那样,但考虑到它的一般性质,也许应该原谅它。

遗憾的是,URI的toURL()方法并没有按照我所希望的方式给出您想要的结果。

URL u = c.toURL();
u.toString()     -> "http://www.foo.combar.html"
u.getAuthority() -> "www.foo.combar.html"  --- Oh dear :(

最好直接使用URL获取所需内容:

URL x = new URL("http://www.foo.com");
URL y = new URL(x, "bar.html");
y.toString() -> "http://www.foo.com/bar.html"

11

URI应该包含最后的分隔符('/'),以便按照您想要的方式进行解析:

URI a = new URI("http://www.foo.com/");

9

URI.resolve 的行为类似于在 HTML 页面上单击带有 href="page1.html" 的链接,如 http://example.org/path/to/menu.html:它会截取最后一个部分(这里是 menu.html),并将 page1.html 放在其位置。

(http://example.org/path/to/menu.html, page1.html) → http://example.org/path/to/page1.html

如果您调用 resolve 的对象是以斜杠结尾表示目录,则也适用于此方法:

(http://example.org/path/to/, page1.html) → http://example.org/path/to/page1.html

如果它没有以斜杠结尾,则结果可能不是您所期望的:

(http://example.org/path/to, page1.html) → http://example.org/path/page1.html(缺少“to”)

如果您知道要拼接的 URI 的第一个参数是目录,但不知道其格式(带或不带尾随斜杠),则此方法可能对您有所帮助:

static URI asDirectory(URI uri) {
    String uriString = uri.toString();
    return !uriString.endsWith("/") ? URI.create(uriString.concat("/")) : uri;
}

2

好的,从URL定义中可以看出,格式为scheme://domain:port/path?query_string#fragment_id

在路径(path)之前应该有3个斜杠(即方案后面两个和路径前面一个)
可能会出现以下两种情况:

    URI中有3个斜杠 => 一切正常
    URI中少于3个斜杠 => 需要在URI末尾添加斜杠

这是我的代码片段:

String url = "http://www.foo.com";
String endSlash="";
int indexOfSlash = 0;
for(int i = 0;i<3;i++){
   int nextIndex = url.indexOf('/',indexOfSlash);
   if(!(nextIndex>0)){
      if(i>1){
         endSlash="/";
      }else{
         throw new MalformedURLException("Bad given url format, mising :// after schema");
      }
   }else{
      indexOfSlash = ++nextIndex;
   }
}
URL rightUrl = new URL(url+endSlash);

1

不同可能性的示例:

    URI uri = new URI( "http://www.example.org");
    System.out.println( "*** "+uri+" ***" );
    System.out.println( uri.resolve( "bar") );
    System.out.println( uri.resolve( "/bar") );
    System.out.println( uri.resolve( "bar/") );
    System.out.println( uri.resolve( "/bar/") );
    System.out.println();
    
    uri = new URI( "http://www.example.org/");
    System.out.println( "*** "+uri+" ***" );
    System.out.println( uri.resolve( "bar") );
    System.out.println( uri.resolve( "/bar") );
    System.out.println( uri.resolve( "bar/") );
    System.out.println( uri.resolve( "/bar/") );
    System.out.println();

    uri = new URI( "http://www.example.org/foo1/foo2");
    System.out.println( "*** "+uri+" ***" );
    System.out.println( uri.resolve( "bar") );
    System.out.println( uri.resolve( "/bar") );
    System.out.println( uri.resolve( "bar/") );
    System.out.println( uri.resolve( "/bar/") );
    System.out.println();
    
    uri = new URI( "http://www.example.org/foo1/foo2/");
    System.out.println( "*** "+uri+" ***" );
    System.out.println( uri.resolve( "bar") );
    System.out.println( uri.resolve( "/bar") );
    System.out.println( uri.resolve( "bar/") );
    System.out.println( uri.resolve( "/bar/") );

输出结果为:

*** http://www.example.org ***
http://www.example.orgbar
http://www.example.org/bar
http://www.example.orgbar/
http://www.example.org/bar/

*** http://www.example.org/ ***
http://www.example.org/bar
http://www.example.org/bar
http://www.example.org/bar/
http://www.example.org/bar/

*** http://www.example.org/foo1/foo2 ***
http://www.example.org/foo1/bar
http://www.example.org/bar
http://www.example.org/foo1/bar/
http://www.example.org/bar/

*** http://www.example.org/foo1/foo2/ ***
http://www.example.org/foo1/foo2/bar
http://www.example.org/bar
http://www.example.org/foo1/foo2/bar/
http://www.example.org/bar/

总结:

  • 情况1-4:如果原始URI没有路径,则resolve使用其参数作为新路径。如果resolve参数不以斜杠开头,则可能会产生错误的域。
  • 情况5-8:如果原始URI是一个带斜杠的域名,则resolve使用其参数作为新路径。双斜杠没有问题。
  • 情况10、12、14和16:如果原始URI有路径,并且resolve参数以斜杠开头,则resolve将URI路径替换为其参数。初始路径被完全丢弃。
  • 情况9、11:如果原始URI具有未以斜杠结尾的路径,并且resolve参数不以斜杠开头,则resolve会丢弃初始uri路径的最后一个元素并添加其参数。
  • 情况13、15:如果原始URI以斜杠结尾的路径,并且resolve参数不以斜杠开头,则resolve添加其参数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接