Hängen Sie die relative URL an java.net.URL an

Lesezeit: 7 Minuten

Benutzeravatar von fulmicoton
Fulmicoton

Vorausgesetzt, ich habe ein java.net.URL-Objekt, das auf sagen wir mal zeigt

http://example.com/myItems oder http://example.com/myItems/

Gibt es irgendwo einen Helfer, um eine relative URL daran anzuhängen? Zum Beispiel anhängen ./myItemId oder myItemId zu bekommen :
http://example.com/myItems/myItemId

  • mögliches Duplikat von Erstellen einer absoluten URL aus einer relativen URL im Java-Servlet

    – Don Roby

    21. September 2011 um 10:15 Uhr

  • Es scheint, dass es keine einfache Lösung gibt. Entweder die URL oder die URI-Klasse unterstützt dies nicht. Auch Apache HttpClient unterstützt dies nicht.

    – Sri

    29. Juli 2017 um 2:43

Andrew Duffys Benutzeravatar
Andrew Duffy

URL hat ein Konstrukteur Das braucht eine Basis URL und ein String spez.

Alternative, java.net.URI hält sich stärker an die Standards und verfügt über eine resolve Methode, um dasselbe zu tun. Ein … kreieren URI von deiner URL verwenden URL.toURI.

  • „URL hat einen Konstruktor, der eine Basis-URL und eine String-Spezifikation akzeptiert.“ – Nicht hilfreich. URL url1 = neue URL(“petstore.swagger.wordnik.com/api/api-docs”); URL url2 = neue URL(url1, „/pet“); System.out.println(url2.toString()) gibt Ihnen: petstore.swagger.wordnik.com/petnicht petstore.swagger.wordnik.com/api/api-docs/pet

    – Benutzer2585038

    14. Okt. 2013 um 17:25

  • Zum Nutzen anderer: Die erste URL-Konstruktormethode funktionierte nicht ganz so, wie ich es erwartet hatte (rtfm, nicht wahr?). Es wird nur der Nicht-Pfad-Teil der Basis-URL verwendet.

    – Jasper Blues

    7. Januar 2016 um 5:31

  • @user2585038: Der zweite Parameter darf nicht mit einem Schrägstrich beginnen. Der Schrägstrich gibt einen „absoluten“ Link an, daher wird der Pfad von URL1 verworfen.

    – Harsel

    21. Juni 2016 um 8:40 Uhr

  • Die URI-Auflösung funktioniert hier eigentlich nur aus Versehen. siehe die Antwort von @Christoph Henkelmann von unten

    – Ittai

    12. Okt. 2016 um 20:17 Uhr

  • Wie @user2585038 erwähnte, berücksichtigt diese Antwort Abschnitt 5.2 (6a) nicht RFC2396 Darin heißt es: „Alle bis auf das letzte Segment der Pfadkomponente des Basis-URI werden in den Puffer kopiert. Mit anderen Worten: Alle Zeichen nach dem letzten (ganz rechts stehenden) Schrägstrich, falls vorhanden, werden ausgeschlossen.“ Diese IMO macht die URI-Auflösung in den meisten Fällen, einschließlich der des OP, unbrauchbar.

    – Steinybot

    23. August 2017 um 22:48

Benutzer-Avatar von Christoph Henkelmann
Christoph Henkelmann

Dieser benötigt keine zusätzlichen Bibliotheken oder Code und liefert das gewünschte Ergebnis:

//import java.net.URL;
URL url1 = new URL("http://petstore.swagger.wordnik.com/api/api-docs?foo=1&bar=baz");
URL url2 = new URL(url1.getProtocol(), url1.getHost(), url1.getPort(), url1.getPath() + "/pet" + "?" + url1.getQuery(), null);
System.out.println(url1);
System.out.println(url2);

Dies druckt:

http://petstore.swagger.wordnik.com/api/api-docs?foo=1&bar=baz
http://petstore.swagger.wordnik.com/api/api-docs/pet?foo=1&bar=baz

Die akzeptierte Antwort funktioniert nur, wenn nach dem Host kein Pfad vorhanden ist (meiner Meinung nach ist die akzeptierte Antwort falsch).

  • MalformedUrlException Warum werfen sie nicht einfach eine ungeprüfte Ausnahme aus :'(

    – gkiko

    9. August 2016 um 9:03 Uhr

  • Ja, das ist scheiße … und es ist inkonsistent: Das Parsen von Zahlen löst ungeprüfte Ausnahmen aus ^^

    – Christoph Henkelmann

    11. August 2016 um 14:49 Uhr

  • Diese Lösung verarbeitet keine abschließenden Schrägstriche. Die Frage liefert zwei Beispiele.

    – rrhrg

    2. August 2018 um 17:08 Uhr

  • url1.getFile().endsWith("/") ? url1.getFile() + "pet" : url1.getFile() + "/pet"?

    – Christoph Henkelmann

    7. November 2018 um 15:01 Uhr

  • @MartinSenne Gut gesehen, ich habe das Beispiel angepasst.

    – Christoph Henkelmann

    27. Mai 2020 um 14:57 Uhr

Sie können einfach das verwenden URI Klasse dafür:

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

Beachten Sie den abschließenden Schrägstrich im Basispfad und das basisrelative Format des Segments, das angehängt wird. Sie können auch die verwenden URIBuilder Klasse vom Apache HTTP-Client:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.3</version>
</dependency>

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() + "https://stackoverflow.com/").resolve("./" + path).getPath());
    return builder.build();
}

  • Das Ergebnis des ersten Codebits ist nicht http://example.com/basepath/relativeAber http://example.com/relativewas den ersten Teil dieser Antwort leider falsch macht.

    – Luciano

    14. Okt. 2019 um 8:14

  • Eigentlich ist der 1. Teil der Antwort richtig; Es funktioniert, wenn ./ nicht angegeben wird, und wenn es mehr als ein / im ersten URI gibt. Z.B x.com:300/z/y/f.txt/////// ~~~ x.com:300/z/y/f.txt/zzccvr.tyt

    – Ironluca

    5. März 2020 um 10:36 Uhr

iains Benutzeravatar
iain

Ich kann nicht glauben, wie böse URI.resolve() Es ist wirklich voller fieser Randfälle.

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"

Die sauberste Lösung, die ich je gesehen habe und die diese Randfälle auf vorhersehbare Weise behandelt, ist:

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();
}

Ergebnisse:

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

Hier ist eine Hilfsfunktion, die ich geschrieben habe, um sie dem URL-Pfad hinzuzufügen:

public static URL concatenate(URL baseUrl, String extraPath) throws URISyntaxException, 
                                                                    MalformedURLException {
    URI uri = baseUrl.toURI();
    String newPath = uri.getPath() + "https://stackoverflow.com/" + extraPath;
    URI newUri = uri.resolve(newPath);
    return newUri.toURL();
}

  • Wenn baseUrl endet mit a / oder extraPath beginnt mit a / Du wirst es wiederholt haben / in der finalen URL. Sie sollten a hinzufügen .normalize() vor dem letzten toURL().

    – Simão Martins

    19. Mai 2017 um 14:42 Uhr


  • Dies funktioniert nicht für eine lokale Datei-URL, die mit file:// beginnen sollte.

    – Sundar Rajan

    2. Juli 2018 um 6:38

  • Wenn baseUrl.getPath() Ist "/" Dadurch wird der Host geändert!!! URI("http://localhost:80").resolve("//foo") => "http://foo" Im Folgenden zeige ich, wie man diese angeht.

    – ja

    2. Dezember 2021 um 11:56 Uhr


Sie können verwenden URIBuilder und die Methode URI#normalize um Duplikate zu vermeiden / in der URI:

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

  • Wenn baseUrl endet mit a / oder extraPath beginnt mit a / Du wirst es wiederholt haben / in der finalen URL. Sie sollten a hinzufügen .normalize() vor dem letzten toURL().

    – Simão Martins

    19. Mai 2017 um 14:42 Uhr


  • Dies funktioniert nicht für eine lokale Datei-URL, die mit file:// beginnen sollte.

    – Sundar Rajan

    2. Juli 2018 um 6:38

  • Wenn baseUrl.getPath() Ist "/" Dadurch wird der Host geändert!!! URI("http://localhost:80").resolve("//foo") => "http://foo" Im Folgenden zeige ich, wie man diese angeht.

    – ja

    2. Dezember 2021 um 11:56 Uhr


Benutzeravatar von twhitbeck
twhitbeck

Ich habe lange nach einer Antwort auf diese Frage gesucht. Die einzige Implementierung, die ich finden kann, ist im Android SDK: Uri.Builder. Ich habe es für meine eigenen Zwecke extrahiert.

private String appendSegmentToPath(String path, String segment) {
  if (path == null || path.isEmpty()) {
    return "https://stackoverflow.com/" + segment;
  }

  if (path.charAt(path.length() - 1) == "https://stackoverflow.com/") {
    return path + segment;
  }

  return path + "https://stackoverflow.com/" + segment;
}

Das Hier habe ich die Quelle gefunden.

In Verbindung mit Apache URIBuilderso verwende ich es: builder.setPath(appendSegmentToPath(builder.getPath(), segment));

1451750cookie-checkHängen Sie die relative URL an java.net.URL an

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy