Was ist die idiomatische Methode, um eine URL oder einen URI in Java zu erstellen?

115

Wie erstelle ich eine URL oder einen URI in Java? Gibt es einen idiomatischen Weg oder Bibliotheken, die dies leicht tun?

Ich muss zulassen, dass von einer Anforderungszeichenfolge ausgegangen wird, verschiedene URL-Teile (Schema, Host, Pfad, Abfragezeichenfolge) analysiert / geändert werden und das Hinzufügen und automatische Codieren von Abfrageparametern unterstützt wird.

jon077
quelle
7
Upvoting der Frage lange nach dem Schließen, da nicht klar ist, ob es eine beliebte, nicht veraltete Lösung für dieses Problem gibt. Ich fand dies, indem ich nach 'Java URL Parameter Class' googelte.
user1445967
4
Meine Absicht war es, einen URL-Builder für Java zu finden, und diese Frage ist zumindest für mich nützlich.
Whirlwin

Antworten:

76

Ab Apache HTTP Component HttpClient 4.1.3 aus dem offiziellen Tutorial :

public class HttpClientTest {
public static void main(String[] args) throws URISyntaxException {
    List<NameValuePair> qparams = new ArrayList<NameValuePair>();
    qparams.add(new BasicNameValuePair("q", "httpclient"));
    qparams.add(new BasicNameValuePair("btnG", "Google Search"));
    qparams.add(new BasicNameValuePair("aq", "f"));
    qparams.add(new BasicNameValuePair("oq", null));
    URI uri = URIUtils.createURI("http", "www.google.com", -1, "/search",
                                 URLEncodedUtils.format(qparams, "UTF-8"), null);
    HttpGet httpget = new HttpGet(uri);
    System.out.println(httpget.getURI());
    //http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq=
}
}

Bearbeiten: ab v4.2 URIUtils.createURI()wurde zugunsten von veraltet URIBuilder:

URI uri = new URIBuilder()
        .setScheme("http")
        .setHost("www.google.com")
        .setPath("/search")
        .setParameter("q", "httpclient")
        .setParameter("btnG", "Google Search")
        .setParameter("aq", "f")
        .setParameter("oq", "")
        .build();
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI());
Chikei
quelle
20
Dies funktioniert, aber ab Version 4.2 ist URIUtils.createURI () zugunsten von URIBuilder veraltet. Positiv zu vermerken ist, dass dieser URIBuilder eine addParameter () -Methode zu haben scheint, sodass das Erstellen von Anforderungszeichenfolgen jetzt zumindest einfacher sein sollte.
Stian
6
URIBuilder builder = new URIBuilder() .setScheme("http") .setHost("www.google.com") .setParameters(qparams);wie @stian sagte
vanduc1102
Println oben druckt Folgendes; google.com/…
Berkan Ercan
61

Als Autor bin ich wahrscheinlich nicht die beste Person, um zu beurteilen, ob mein URL / URI-Builder gut ist , aber hier ist es trotzdem: https://github.com/mikaelhg/urlbuilder

Ich wollte eine möglichst einfache Komplettlösung ohne Abhängigkeiten außerhalb des JDK, also musste ich meine eigene rollen.

Mikael Gueck
quelle
6
Es sieht gut aus, Mikael. Hast du darüber nachgedacht, es in Maven Central zu veröffentlichen? Ich weiß, dass es klein ist, aber es einfacher macht. Ich kann außer in JAX-RS keine ähnliche Klasse finden. Das Fehlen von Abhängigkeiten ist definitiv ein Plus.
Barry Pitman
Es sieht gut aus, aber da es ein Builder und damit veränderlich ist, warum gibt es Setter nur für Parameter, aber nicht für Host, Port, Protokoll und Pfad? Und auch für diese gibt es keine Getter. UPD: Oh, es ist nicht veränderlich - setParameter erstellt einen Klon. Nun, setHost / setPort / ... könnte genauso funktionieren. Oder vielleicht wäre eine veränderbare Version auch schön zu haben.
mvmn
3
"Einfachste Komplettlösung ohne Abhängigkeiten" - Klingt so, als wüssten Sie, worauf es ankommt! Ihre Antwort sollte die akzeptierte sein. Das Einbeziehen des gesamten HttpClient (mit all seinen Versionsaktualisierungen und sogar das Verwerfen der API, um die es in dieser Frage geht) nur zum Erstellen einer URL ist das, was zu kopflastigen, von Fehlern durchsetzten Apps führt.
Stijn de Witt
2
Endlich auf Maven Central, und ich habe nur vier Jahre gebraucht, um fertig zu werden.
Mikael Gueck
@mikaelhg Danke! Ich brauche genau in diesem Moment!
Fabian Damken
29

Die Verwendung von HTTPClient hat gut funktioniert.

protected static String createUrl(List<NameValuePair> pairs) throws URIException{

  HttpMethod method = new GetMethod("http://example.org");
  method.setQueryString(pairs.toArray(new NameValuePair[]{}));

  return method.getURI().getEscapedURI();

}
jon077
quelle
6
Dies ist jetzt veraltete Funktionalität. Weiß jemand, wie man das neue HTTP-Komponentenpaket verwendet, um dasselbe zu tun, weil es mich verblüfft hat.
Link19
3
Die neue 4x-Version unterstützt dies nicht mehr.
Joscha
13

Es gibt viele Bibliotheken, die Ihnen beim Erstellen von URIs helfen können (erfinden Sie das Rad nicht neu). Hier sind drei, um Ihnen den Einstieg zu erleichtern:


Java EE 7

import javax.ws.rs.core.UriBuilder;
...
return UriBuilder.fromUri(url).queryParam(key, value).build();

org.apache.httpcomponents: httpclient: 4.5.2

import org.apache.http.client.utils.URIBuilder;
...
return new URIBuilder(url).addParameter(key, value).build();

org.springframework: spring-web: 4.2.5.RELEASE

import org.springframework.web.util.UriComponentsBuilder;
...
return UriComponentsBuilder.fromUriString(url).queryParam(key, value).build().toUri();

Siehe auch: GIST> URI Builder-Tests

Nick Grealy
quelle
2
EE 7 ist die richtige Antwort. Sie müssen lediglich die gesamte Suite der EE-Bibliotheken abrufen, eine JAX-RS-Implementierung auswählen, Konflikte mit der jax-rs-Version lösen und als Belohnung eine praktische UriBuilder-Klasse erhalten, die wirklich gut funktioniert. Sarkasmus beiseite, das ist die richtige Antwort. :)
tekHedd
10

Verwenden Sie OkHttp

Es ist 2020 und es gibt eine sehr beliebte Bibliothek namens OkHttp, die 35K- mal auf GitHub gespielt wurde. Mit dieser Bibliothek können Sie eine URL wie folgt erstellen:

import okhttp3.HttpUrl;

URL url = new HttpUrl.Builder()
    .scheme("http")
    .host("example.com")
    .port(4567)
    .addPathSegment("foldername/1234")
    .addQueryParameter("abc", "xyz")
    .build().url();
Tyler Long
quelle
Ich habe einen Tippfehler behoben, es ist addPathSegment(nicht addPathSegments).
PapaFreud
1

Nach dem Lambast für das Vorschlagen der URL-Klasse. Ich werde den Rat des Kommentators befolgen und stattdessen die URI-Klasse vorschlagen . Ich schlage vor, Sie sehen sich die Konstruktoren für einen URI genau an, da die Klasse nach ihrer Erstellung sehr unveränderlich ist.
Ich denke, mit diesem Konstruktor können Sie alles in der URI festlegen, was Sie benötigen könnten.

URI(String scheme, String userInfo, String host, int port, String path, String query, String fragment)
          Constructs a hierarchical URI from the given components.
Mike Pone
quelle
8
Es bietet jedoch keine Funktionalität zum Erstellen und Codieren einer Abfragezeichenfolge aus einer Reihe von Name-Wert-Paaren.
Link19
4
Wie das Wunderkind zu Alan Partridge sagte - man kann keine Verschlechterung der Unveränderlichkeit haben, es ist entweder oder es ist nicht ;-) youtube.com/watch?v=_lvFns5Lubc
Stewart
Der Konstruktor von URI macht böse Dinge mit dem Pfad. Weitere Informationen finden Sie unter blog.palominolabs.com/2013/10/03/… .
mpierce
1
Lassen Sie diese Antwort als Beispiel dafür stehen, wie Sie dies dann NICHT tun sollen.
Mike Pone
1
String-Abfrage ... Vielen Dank an Sun / Oracle für die Granularität. Wir werden einfach alle Leerzeichen durch Pluszeichen ersetzen, alle Parameter uri-codieren und sie alle selbst mit kaufmännischen Und-Symbolen verknüpfen. Dann ... schlagen wir wiederholt auf den Tisch
Stijn de Witt