Come verificare la presenza di un URL valido in Java?


93

Qual è il modo migliore per verificare se un URL è valido in Java?

Se ha provato a chiamare new URL(urlString)e prendere un MalformedURLException, ma sembra essere felice con tutto ciò che inizia con http://.

Non mi interessa stabilire una connessione, solo la validità. C'è un metodo per questo? Un'annotazione in Hibernate Validator? Dovrei usare una regex?

Modifica: alcuni esempi di URL accettati sono http://***e http://my favorite site!.


Come definisci la validità se non intendi stabilire una connessione?
Michael Myers

2
Puoi fornire un esempio di qualcosa che non è un URL valido URLaccettato dal costruttore?
uckelman

1
@mmyers: la validità dovrebbe essere determinata dalle RFC 2396 e 2732, quelle che definiscono cos'è un URL.
uckelman

4
@uckelman: praticamente qualsiasi cosa. " http://***" funziona. " http://my favorite site!" funziona. Non riesco a far sì che generi un'eccezione (quando http: // è all'inizio.)
Eric Wilson,

2
possibile duplicato dell'URL
JasonB

Risposte:


101

Prendi in considerazione l'utilizzo della classe UrlValidator di Apache Commons

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

Ci sono diverse proprietà che possono essere impostate per controllare come si comporta questa classe, per impostazione predefinita http, httpse ftpsono accettati.


7
non sembra funzionare con i domini più recenti come .london ecc.
VH

che ne dici degli URL intranet?
Puneet

Non convalida gli URL con trattini bassi.
Udit Kumawat

Non funziona con nuovi TLD e nomi di dominio locali, ad esempio local, ecc.

Non sono riuscito a far funzionare UrlValidator con il nostro strano dominio intranet di primo livello. Quelli comuni come .com, .org e simili. Non mi interessa creare una RegExp per questa materia, quindi new URL(name).toURI()diventa la soluzione.
Avec

59

Ecco come ho provato e trovato utile,

URL u = new URL(name); // this would check for the protocol
u.toURI(); // does the extra checking required for validation of URI 

1
Bene. Usare solo un nuovo URL (nome) accetta quasi tutto. Url.toURI (); è esattamente ciò che lo sviluppatore sta cercando, senza utilizzare altre librerie / framework!
justastefan

2
Ciò non funzionerà anche per URL non corretti come http: /google.com. Ho usato UrlValidator da Apache Commons.
starf

1
Questo è davvero pericoloso. Vedo che ci sono molti altri articoli là fuori con questo esempio. URL u = new URL(http://google).toURI();non genererà un'eccezione.
Sonu Oommen

@SonuOommen forse perché new URL(http://google)è valido ^^ abbiamo un sacco di dominio interno nella mia azienda come questo
user43968

8

Mi piacerebbe postare questo come commento alla risposta di Tendayi Mawushe , ma temo che non ci sia abbastanza spazio;)

Questa è la parte rilevante dalla fonte UrlValidator di Apache Commons :

/**
 * 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;

Puoi facilmente costruire il tuo validatore da lì.


6

Il modo più "infallibile" è verificare la disponibilità dell'URL:

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

4

Il mio approccio preferito, senza librerie esterne:

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) {
}

3

A giudicare dal codice sorgente per URIil

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

costruttore fa più convalida rispetto agli altri costruttori. Potresti provare quello, ma YMMV.


3

Non mi è piaciuta nessuna delle implementazioni (perché usano un Regex che è un'operazione costosa, o una libreria che è eccessiva se hai solo bisogno di un metodo), quindi ho finito per usare la classe java.net.URI con alcuni controlli extra e limitando i protocolli a: http, https, file, ftp, mailto, news, urn.

E sì, catturare le eccezioni può essere un'operazione costosa, ma probabilmente non così grave come le espressioni regolari:

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

2

pacchetto validatore:

Sembra che ci sia un bel pacchetto di Yonatan Matalon chiamato UrlUtil . Citando la sua API:

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

Approccio di Sun: controlla l'indirizzo di rete

Il sito Java di Sun offre un tentativo di connessione come soluzione per la convalida degli URL.

Altri frammenti di codice regex:

Sono presenti tentativi di convalida dell'espressione regolare sul sito Oracle e su weberdev.com .


1
Quel codice serve per controllare i collegamenti, il che è un problema diverso. Questa domanda riguarda la validità dell'URL, non se è possibile stabilire una connessione ad esso.
Michael Myers

Questo esempio riguarda il controllo se l'URL è disponibile, non se è ben formato.
uckelman

D'accordo, ha aggiunto altri approcci.
Adam Matan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.