Comment vérifier une URL valide en Java?

93

Quelle est la meilleure façon de vérifier si une URL est valide en Java?

Si essayé d'appeler new URL(urlString)et d'attraper un MalformedURLException, mais il semble être satisfait de tout ce qui commence par http://.

Je ne suis pas préoccupé par l'établissement d'une connexion, juste la validité. Existe-t-il une méthode pour cela? Une annotation dans Hibernate Validator? Dois-je utiliser une regex?

Modifier: quelques exemples d'URL acceptées sont http://***et http://my favorite site!.

Eric Wilson
la source
Comment définissez-vous la validité si vous n'allez pas établir de connexion?
Michael Myers
2
Pouvez-vous donner un exemple de quelque chose qui n'est pas une URL valide acceptée par le URLconstructeur?
uckelman
1
@mmyers: La validité doit être déterminée par les RFC 2396 et 2732, celles qui définissent ce qu'est une URL.
uckelman
4
@uckelman: à peu près n'importe quoi. " http://***" fonctionne. " http://my favorite site!" fonctionne. Je ne peux pas faire en sorte qu'il lance une exception (quand http: // est au début.)
Eric Wilson
2
duplication possible de l' URL
JasonB

Réponses:

101

Envisagez d'utiliser la classe Apache Commons UrlValidator

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

Il y a plusieurs propriétés que vous pouvez définir pour contrôler la façon dont cette classe se comporte, par défaut http, httpset ftpsont acceptés.

Tendayi Mawushe
la source
7
il ne semble pas fonctionner avec les domaines plus récents tels que .london etc
VH
qu'en est-il des URL intranet?
Puneet
Il ne valide pas les URL avec des traits de soulignement.
Udit Kumawat
Ne fonctionne pas avec les nouveaux TLD et les noms de domaine locaux, par exemple local, etc.
Je n'ai pas pu faire fonctionner UrlValidator avec notre domaine de premier niveau intranet bizarre. Les plus courants comme .com, .org, etc. Je ne suis pas intéressé par la création d'un RegExp pour cette question afin de new URL(name).toURI()devenir la solution.
Avec
59

Voici comment j'ai essayé et trouvé utile,

URL u = new URL(name); // this would check for the protocol
u.toURI(); // does the extra checking required for validation of URI 
Prasanna Pilla
la source
1
Bon. Utiliser juste une nouvelle URL (nom) accepte presque tout. L'url.toURI (); est exactement ce que le développeur recherche - sans utiliser d'autres bibliothèques / frameworks!
justastefan
2
Cela ne fonctionnera pas non plus pour les URL mal formées telles que http: /google.com. J'ai utilisé UrlValidator d'Apache Commons.
starf
1
Celui-ci est vraiment dangereux. Je vois qu'il y a beaucoup d'autres articles avec cet exemple. URL u = new URL(http://google).toURI();ne lèvera pas d'exception.
Sonu Oommen
@SonuOommen peut-être parce que new URL(http://google)c'est valide ^^ nous avons beaucoup de domaine interne dans mon entreprise comme celui-ci
user43968
8

J'adorerais poster ceci en commentaire de la réponse de Tendayi Mawushe , mais j'ai peur qu'il n'y ait pas assez de place;)

Voici la partie pertinente de la source Apache Commons UrlValidator :

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

Vous pouvez facilement créer votre propre validateur à partir de là.

user123444555621
la source
6

Le moyen le plus "infaillible" est de vérifier la disponibilité de l'URL:

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

Mon approche préférée, sans bibliothèques externes:

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
la source
3

A en juger par le code source de URI, le

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

constructeur fait plus de validation que les autres constructeurs. Vous pourriez essayer celui-là, mais YMMV.

Uckelman
la source
3

Je n'ai aimé aucune des implémentations (car elles utilisent un Regex qui est une opération coûteuse, ou une bibliothèque qui est excessive si vous n'avez besoin que d'une seule méthode), alors j'ai fini par utiliser la classe java.net.URI avec certains vérifications supplémentaires, et en limitant les protocoles à: http, https, fichier, ftp, mailto, news, urn.

Et oui, intercepter des exceptions peut être une opération coûteuse, mais probablement pas aussi mauvaise que les expressions régulières:

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
la source
2

package de validation:

Il semble y avoir un joli paquet de Yonatan Matalon appelé UrlUtil . Citant son API:

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

L'approche de Sun - vérifier l'adresse réseau

Le site Java de Sun propose une tentative de connexion comme solution pour valider les URL.

Autres extraits de code regex:

Il y a des tentatives de validation regex sur le site d'Oracle et sur weberdev.com .

Adam Matan
la source
1
Ce code sert à vérifier les liens, ce qui est un problème différent. Cette question porte sur la validité de l'URL, pas sur la possibilité d'établir une connexion avec celle-ci.
Michael Myers
Cet exemple consiste à vérifier si l'URL est disponible, pas si elle est bien formée.
uckelman
D'accord, ajout d'autres approches.
Adam Matan