W3docs

Java URL-Klasse

URLs in Java mit der URL-Klasse parsen und darstellen — Protokoll, Host, Port, Pfad, Abfrage.

Eine URL (Uniform Resource Locator) benennt eine Ressource und den Weg, sie zu erreichen: https://www.example.com:443/docs?q=net#top. Java modelliert dies mit java.net.URL, das eine URL sowohl in ihre Bestandteile zerlegt als auch eine Verbindung öffnen kann, um sie abzurufen. Dieses Kapitel behandelt das Parsen und die Struktur; das Öffnen einer Verbindung zum tatsächlichen Abrufen von Bytes wird in Java URLConnection behandelt.

Diese Seite behandelt die Bestandteile einer URL, die Getter, die sie zugänglich machen, wie man eine URL aufbaut (einschließlich der Auflösung relativer Referenzen) und warum moderner Code URI anstelle der veralteten URL-String-Konstruktoren verwenden sollte.

Der Aufbau einer URL

  https://user:[email protected]:8443/docs/java?topic=net#intro
  └─┬─┘   └──┬──┘ └──────┬───────┘└┬─┘└───┬────┘ └────┬────┘└─┬─┘
 protocol  userInfo     host     port   path        query    ref

java.net.URL stellt jedes Element über einen Getter bereit: getProtocol(), getUserInfo(), getHost(), getPort(), getPath(), getQuery() und getRef() (das Fragment). getPort() gibt -1 zurück, wenn kein Port angegeben ist; getDefaultPort() liefert den Standardwert des Protokolls (80 für http, 443 für https).

Eine URL aufbauen

URL url = new URL("https://example.com/path?x=1");      // from a string
URL rel = new URL(base, "../images/logo.png");          // relative to a base

Der zweiargumentige Konstruktor löst eine relative Referenz gegen eine Basis-URL auf — nach derselben Regel, die ein Browser für einen Link auf einer Seite verwendet. So wandelt man ../images/logo.png auf einer Seite unter /a/b/page.html in die absolute URL /a/images/logo.png um.

URI für Parsing und Validierung bevorzugen

Auf modernen JDKs sind die URL-String-Konstruktoren veraltet. URL ist nun für das Öffnen von Verbindungen gedacht, nicht für das Parsen oder Validieren. Für reines Parsen verwende java.net.URI und konvertiere, wenn du tatsächlich eine Verbindung benötigst:

URI uri = URI.create("https://example.com/path?x=1");   // parse / validate
URL url = uri.toURL();                                   // only to open a connection

Es gibt auch eine bekannte Falle: URL.equals() und URL.hashCode() können DNS-Auflösungen durchführen, um Hosts zu vergleichen, was sie langsam und netzwerkabhängig macht. Speichere URL-Objekte niemals in einem HashSet oder verwende sie als Map-Schlüssel — nutze stattdessen URI, dessen Gleichheitsvergleich rein textuell ist.

Ein praktisches Beispiel: URLs zerlegen und auflösen

Dieses Programm zerlegt eine vollständig aufgebaute URL in ihre Bestandteile, löst eine relative Referenz auf und stellt URL der Parsing-freundlichen URI gegenüber — alles offline, da das Parsen keine Netzwerkverbindung erfordert.

java— editable, runs on the server

Was man aus der Ausgabe mitnehmen kann:

  • Jeder Getter hat einen bezeichneten Abschnitt aus dem einzelnen URL-String extrahiert: Protokoll, Benutzerinfo, Host, Port, Pfad, Abfrage und das #intro-Fragment über getRef(). Eine URL ist ein strukturierter Wert, nicht nur Text — sie einmal zu parsen und die Felder auszulesen ist besser als String.split manuell auf / und ? anzuwenden.
  • Die URL ohne Port meldete getPort() == -1, während getDefaultPort() den Wert 80 zurückgab. Der Unterschied ist wichtig, wenn du eine Verbindung aufbaust: -1 bedeutet, dass der Port weggelassen wurde, und du fällst auf den Protokollstandard zurück, anstatt -1 als echten Port zu behandeln.
  • base.resolve("../images/logo.png") erzeugte eine absolute URL, indem aus /a/b/ herausgegangen wurde — genau die Auflösung relativer Links, die ein Browser durchführt. Relative Referenzen werden gegen eine Basis aufgelöst, sodass der Pfad der Basis bestimmt, wohin .. führt.
  • Das Beispiel baute die URL über URI.create(...).toURL() auf, anstatt das veraltete new URL(String) zu verwenden. Auf modernen JDKs ist das der empfohlene Weg: mit URI parsen und validieren, zu URL nur in dem Moment konvertieren, in dem eine Verbindung geöffnet wird.
  • URI.equals verglich zwei identische URIs textuell und gab true zurück, ohne Netzwerkzugriff. Das ist der sichere Weg zum Vergleichen und als Map-Schlüssel zu verwenden — URL.equals hätte möglicherweise eine DNS-Abfrage zur Auflösung des Hosts ausgelöst, was langsam ist und offline scheitern kann.

Sobald du eine URL hast, ist der nächste Schritt normalerweise, sie zu öffnen. Für einen Low-Level-Stream rufe url.openConnection() auf (siehe Java URLConnection); für eine moderne, High-Level-HTTP-API bevorzuge den Java HttpClient.

Übungen

Übung
Ein Teammitglied speichert heruntergeladene Ressourcen in einem 'HashSet<URL>', um Duplikate zu überspringen, und stellt fest, dass das Programm langsam ist und manchmal hängt, wenn es offline ist. Was ist die korrekte Erklärung und Lösung?
Ein Teammitglied speichert heruntergeladene Ressourcen in einem 'HashSet<URL>', um Duplikate zu überspringen, und stellt fest, dass das Programm langsam ist und manchmal hängt, wenn es offline ist. Was ist die korrekte Erklärung und Lösung?
Was this page helpful?