将相对URL附加到java.net.URL

ful*_*ton 34 java url

如果我有一个java.net.URL对象,指向让我们说

http://example.com/myItems 要么 http://example.com/myItems/

是否有某个帮助器在某处附加一些相对URL?例如追加./myItemIdmyItemId得到: http://example.com/myItems/myItemId

And*_*ffy 26

URL有一个带基数和规格的构造函数.URLString

或者,java.net.URI更贴近标准,并有一个resolve方法来做同样的事情.URI从您的URL使用中创建一个URL.toURI.

  • "URL有一个构造函数,它接受一个基本URL和一个String规范." - 没用.网址url1 =新网址("http://petstore.swagger.wordnik.com/api/api-docs"); URL url2 =新网址(url1,"/ pet"); System.out.println(url2.toString())为您提供:http://petstore.swagger.wordnik.com/pet,而不是http://petstore.swagger.wordnik.com/api/api-docs/pet (21认同)
  • @ user2585038:第二个参数不能以斜杠开头.斜杠表示"绝对"链接,因此丢弃url1的路径. (5认同)
  • 为了其他人的利益:第一个URL构造函数方法不能像我预期的那样工作(rtfm,嗯?).仅使用baseURL的非路径部分. (2认同)
  • URI 解析实际上只是在这里错误地起作用。从下面看@Christoph Henkelmann 的回答 (2认同)
  • 正如@user2585038 提到的,这个答案没有考虑到 [RFC2396](https://www.ietf.org/rfc/rfc2396.txt) 中的第 5.2 (6a) 节,该节指出:“除了基本 URI 的最后一段之外的所有内容路径组件被复制到缓冲区。换句话说,最后一个(最右边的)斜杠字符之后的任何字符(如果有)都被排除在外。” 此 IMO 使 URI 解析在大多数情况下无法使用,包括 OP 的情况。 (2认同)

Chr*_*ann 25

这个不需要任何额外的库或代码,并给出了所需的结果:

URL url1 = new URL("http://petstore.swagger.wordnik.com/api/api-docs");
URL url2 = new URL(url1.getProtocol(), url1.getHost(), url1.getPort(), url1.getFile() + "/pet", null);
System.out.println(url1);
System.out.println(url2);
Run Code Online (Sandbox Code Playgroud)

这打印:

http://petstore.swagger.wordnik.com/api/api-docs
http://petstore.swagger.wordnik.com/api/api-docs/pet
Run Code Online (Sandbox Code Playgroud)

只有在主机之后没有路径(恕我直言,接受的答案是错误的)时,接受的答案才有效

  • 此解决方案不处理尾部斜杠。问题提供了两个例子。 (2认同)

Sco*_*ock 17

您只需使用URI该类即可:

import java.net.URI;
import org.apache.http.client.utils.URIBuilder;

URI uri = URI.create("http://example.com/basepath/");
URI uri2 = uri.resolve("./relative");
// => http://example.com/basepath/relative
Run Code Online (Sandbox Code Playgroud)

请注意基本路径上的尾部斜杠以及要附加的段的基本相对格式。您还可以使用URIBuilderApache HTTP 客户端中的类:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.3</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

...

import java.net.URI;
import org.apache.http.client.utils.URIBuilder;

URI uri = URI.create("http://example.com/basepath");
URI uri2 = appendPath(uri, "relative");
// => http://example.com/basepath/relative

public URI appendPath(URI uri, String path) {
    URIBuilder builder = new URIBuilder(uri);
    builder.setPath(URI.create(builder.getPath() + "/").resolve("./" + path).getPath());
    return builder.build();
}
Run Code Online (Sandbox Code Playgroud)

  • 第一段代码的结果是***不是***`http://example.com/basepath/relative`,而是`http://example.com/relative`,不幸的是,这是第一部分回答不正确。 (6认同)

iai*_*ain 13

我不敢相信URI.resolve()它充满了令人讨厌的边缘情况,真的是多么令人讨厌。

new URI("http://localhost:80").resolve("foo") => "http://localhost:80foo"
new URI("http://localhost:80").resolve("//foo") => "http://foo"
new URI("http://localhost:80").resolve(".//foo") => "http://foo"
Run Code Online (Sandbox Code Playgroud)

我见过的以可预测的方式处理这些边缘情况的最简洁的解决方案是:

URI addPath(URI uri, String path) {
    String newPath;
    if (path.startsWith("/")) newPath = path.replaceAll("//+", "/");
    else if (uri.getPath().endsWith("/")) newPath = uri.getPath() + path.replaceAll("//+", "/");
    else newPath = uri.getPath() + "/" + path.replaceAll("//+", "/");

    return uri.resolve(newPath).normalize();
}
Run Code Online (Sandbox Code Playgroud)

结果:

jshell> addPath(new URI("http://localhost"), "sub/path")
$3 ==> http://localhost/sub/path

jshell> addPath(new URI("http://localhost/"), "sub/path")
$4 ==> http://localhost/sub/path

jshell> addPath(new URI("http://localhost/"), "/sub/path")
$5 ==> http://localhost/sub/path

jshell> addPath(new URI("http://localhost/random-path"), "/sub/path")
$6 ==> http://localhost/sub/path

jshell> addPath(new URI("http://localhost/random-path"), "./sub/path")
$7 ==> http://localhost/random-path/sub/path

jshell> addPath(new URI("http://localhost/random-path"), "../sub/path")
$8 ==> http://localhost/sub/path

jshell> addPath(new URI("http://localhost"), "../sub/path")
$9 ==> http://localhost/../sub/path

jshell> addPath(new URI("http://localhost/"), "//sub/path")
$10 ==> http://localhost/sub/path

jshell> addPath(new URI("http://localhost/"), "//sub/./path")
$11 ==> http://localhost/sub/path
Run Code Online (Sandbox Code Playgroud)


her*_*rau 7

您可以使用URIBuilder和方法来避免URI 中的URI#normalize重复:/

URIBuilder uriBuilder = new URIBuilder("http://example.com/test");
URI uri = uriBuilder.setPath(uriBuilder.getPath() + "/path/to/add")
          .build()
          .normalize();
// expected : http://example.com/test/path/to/add
Run Code Online (Sandbox Code Playgroud)


And*_*erd 6

这是我写的一个辅助函数,用于添加到url路径:

public static URL concatenate(URL baseUrl, String extraPath) throws URISyntaxException, 
                                                                    MalformedURLException {
    URI uri = baseUrl.toURI();
    String newPath = uri.getPath() + '/' + extraPath;
    URI newUri = uri.resolve(newPath);
    return newUri.toURL();
}
Run Code Online (Sandbox Code Playgroud)

  • 如果`baseUrl`以`/`或`extraPath`开头,以`/`开头,你将在最终的URL中重复`/`.你应该在最后一个`toURL()`之前加一个`.normalize()`. (2认同)