Wie überprüfe ich eine gültige URL in Java?

92

Wie kann ich am besten überprüfen, ob eine URL in Java gültig ist?

Wenn versucht wird, einen anzurufen new URL(urlString)und zu fangen MalformedURLException, scheint er mit allem, was damit beginnt, zufrieden zu sein http://.

Es geht mir nicht darum, eine Verbindung herzustellen, sondern nur um die Gültigkeit. Gibt es dafür eine Methode? Eine Anmerkung in Hibernate Validator? Soll ich einen regulären Ausdruck verwenden?

Bearbeiten: Einige Beispiele für akzeptierte URLs sind http://***und http://my favorite site!.

Eric Wilson
quelle
Wie definieren Sie die Gültigkeit, wenn Sie keine Verbindung herstellen möchten?
Michael Myers
2
Können Sie ein Beispiel für etwas geben, das keine gültige URL ist, die der URLKonstruktor akzeptiert?
uckelman
1
@mmyers: Die Gültigkeit sollte durch die RFCs 2396 und 2732 bestimmt werden, die definieren, was eine URL ist.
uckelman
4
@uckelman: Fast alles. " http://***" funktioniert. " http://my favorite site!" funktioniert. Ich kann es nicht dazu bringen, eine Ausnahme auszulösen (wenn http: // am Anfang steht)
Eric Wilson
2
Mögliches Duplikat der Validierungs-URL in Java
JasonB

Antworten:

99

Erwägen Sie die Verwendung der Apache Commons UrlValidator-Klasse

UrlValidator urlValidator = new UrlValidator();
urlValidator.isValid("http://my favorite site!");

Es gibt mehrere Eigenschaften , die Sie festlegen können , kontrollieren , wie diese Klasse verhält sich standardmäßig http, httpsund ftpakzeptiert werden.

Tendayi Mawushe
quelle
7
Es scheint nicht mit neueren Domains wie .london usw. zu funktionieren
VH
Wie wäre es mit Intranet-URLs?
Puneet
URLs werden nicht mit Unterstrichen überprüft.
Udit Kumawat
Funktioniert nicht mit neuen TLDs und lokalen Domainnamen, z. B. localusw.
Ich konnte UrlValidator nicht dazu bringen, mit unserer seltsamen Intranet-Top-Level-Domain zu arbeiten. Die gängigen wie .com, .org und solche Werke. Ich bin nicht daran interessiert, ein RegExp für diese Angelegenheit zu erstellen, damit new URL(name).toURI()es zur Lösung wird.
Avec
59

Hier ist, wie ich es versucht und nützlich gefunden habe:

URL u = new URL(name); // this would check for the protocol
u.toURI(); // does the extra checking required for validation of URI 
Prasanna Pilla
quelle
1
Gut. Die Verwendung einer neuen URL (Name) akzeptiert fast alles. Die url.toURI (); ist genau das, wonach der Entwickler sucht - ohne andere Bibliotheken / Frameworks zu verwenden!
Justastefan
2
Dies funktioniert auch nicht für fehlerhafte URLs wie http: /google.com. Ich habe UrlValidator von Apache Commons verwendet.
Starf
1
Dieser ist wirklich gefährlich. Ich sehe, dass es mit diesem Beispiel viele andere Artikel gibt. URL u = new URL(http://google).toURI();wird keine Ausnahme auslösen.
Sonu Oommen
@ SonuOommen vielleicht, weil new URL(http://google)es gültig ist ^^ Wir haben viele interne Domains in meiner Firma wie diese
user43968
8

Ich würde dies gerne als Kommentar zu Tendayi Mawushes Antwort posten , aber ich fürchte, es gibt nicht genug Platz;)

Dies ist der relevante Teil aus der Apache Commons UrlValidator- Quelle :

/**
 * This expression derived/taken from the BNF for URI (RFC2396).
 */
private static final String URL_PATTERN =
        "/^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?/";
//         12            3  4          5       6   7        8 9

/**
 * Schema/Protocol (ie. http:, ftp:, file:, etc).
 */
private static final int PARSE_URL_SCHEME = 2;

/**
 * Includes hostname/ip and port number.
 */
private static final int PARSE_URL_AUTHORITY = 4;

private static final int PARSE_URL_PATH = 5;

private static final int PARSE_URL_QUERY = 7;

private static final int PARSE_URL_FRAGMENT = 9;

Von dort aus können Sie ganz einfach Ihren eigenen Validator erstellen.

user123444555621
quelle
6

Am einfachsten ist es, die Verfügbarkeit der URL zu überprüfen:

public boolean isURL(String url) {
  try {
     (new java.net.URL(url)).openStream().close();
     return true;
  } catch (Exception ex) { }
  return false;
}
Joe
quelle
4

Mein Lieblingsansatz ohne externe Bibliotheken:

try {
    URI uri = new URI(name);

    // perform checks for scheme, authority, host, etc., based on your requirements

    if ("mailto".equals(uri.getScheme()) {/*Code*/}
    if (uri.getHost() == null) {/*Code*/}

} catch (URISyntaxException e) {
}
Andrei Volgin
quelle
3

Gemessen am Quellcode für URI, die

public URL(URL context, String spec, URLStreamHandler handler)

Der Konstruktor validiert mehr als die anderen Konstruktoren. Sie könnten das versuchen, aber YMMV.

uckelman
quelle
3

Ich mochte keine der Implementierungen (weil sie einen Regex verwenden, was eine teure Operation ist, oder eine Bibliothek, die ein Overkill ist, wenn Sie nur eine Methode benötigen), also habe ich mit einigen die Klasse java.net.URI verwendet zusätzliche Überprüfungen und Beschränkung der Protokolle auf: http, https, file, ftp, mailto, news, urn.

Und ja, Ausnahmen zu fangen kann eine teure Operation sein, aber wahrscheinlich nicht so schlimm wie reguläre Ausdrücke:

final static Set<String> protocols, protocolsWithHost;

static {
  protocolsWithHost = new HashSet<String>( 
      Arrays.asList( new String[]{ "file", "ftp", "http", "https" } ) 
  );
  protocols = new HashSet<String>( 
      Arrays.asList( new String[]{ "mailto", "news", "urn" } ) 
  );
  protocols.addAll(protocolsWithHost);
}

public static boolean isURI(String str) {
  int colon = str.indexOf(':');
  if (colon < 3)                      return false;

  String proto = str.substring(0, colon).toLowerCase();
  if (!protocols.contains(proto))     return false;

  try {
    URI uri = new URI(str);
    if (protocolsWithHost.contains(proto)) {
      if (uri.getHost() == null)      return false;

      String path = uri.getPath();
      if (path != null) {
        for (int i=path.length()-1; i >= 0; i--) {
          if ("?<>:*|\"".indexOf( path.charAt(i) ) > -1)
            return false;
        }
      }
    }

    return true;
  } catch ( Exception ex ) {}

  return false;
}
Isapir
quelle
2

Validator-Paket:

Es scheint ein schönes Paket von Yonatan Matalon namens UrlUtil zu geben . Zitiert seine API:

isValidWebPageAddress(java.lang.String address, boolean validateSyntax, 
                      boolean validateExistance) 
Checks if the given address is a valid web page address.

Suns Ansatz - Überprüfen Sie die Netzwerkadresse

Die Java-Site von Sun bietet einen Verbindungsversuch als Lösung für die Überprüfung von URLs.

Andere Regex-Code-Schnipsel:

Es gibt Regex-Validierungsversuche auf der Oracle-Website und auf weberdev.com .

Adam Matan
quelle
1
Dieser Code dient zum Überprüfen von Links, was ein anderes Problem darstellt. Bei dieser Frage geht es um die Gültigkeit der URL, nicht darum, ob eine Verbindung zu ihr hergestellt werden kann.
Michael Myers
In diesem Beispiel wird überprüft, ob die URL verfügbar ist und nicht, ob sie wohlgeformt ist.
uckelman
Einverstanden, fügte andere Ansätze hinzu.
Adam Matan