¿Cómo verificar una URL válida en Java?

93

¿Cuál es la mejor forma de comprobar si una URL es válida en Java?

Si trató de llamar new URL(urlString)y atrapar a MalformedURLException, pero parece estar contento con cualquier cosa que comience con http://.

No me preocupa establecer una conexión, solo validez. ¿Existe algún método para esto? ¿Una anotación en Hibernate Validator? ¿Debería usar una expresión regular?

Editar: algunos ejemplos de URL aceptadas son http://***y http://my favorite site!.

Eric Wilson
fuente
¿Cómo define la validez si no va a establecer una conexión?
Michael Myers
2
¿Puede dar un ejemplo de algo que no sea una URL válida que URLacepte el constructor?
uckelman
1
@mmyers: la validez debe ser determinada por las RFC 2396 y 2732, las que definen qué es una URL.
uckelman
4
@uckelman: Casi cualquier cosa. " http://***" funciona. " http://my favorite site!" funciona. No puedo hacer que genere una excepción (cuando http: // está al principio)
Eric Wilson
2
posible duplicado de Validación de URL en Java
JasonB

Respuestas:

101

Considere usar la clase Apache Commons UrlValidator

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

Hay varias propiedades que se pueden establecer para controlar cómo, por defecto, ésta se comporta de clase http, httpsy ftpse aceptan.

Tendayi Mawushe
fuente
7
no parece funcionar con dominios más nuevos como .london, etc.
VH
¿qué hay de las URL de intranet?
Puneet
No valida las URL con guiones bajos.
Udit Kumawat
No funciona con nuevos TLD y nombres de dominio locales, por ejemplo local, etc.
No pude hacer que UrlValidator funcionara con nuestro extraño dominio de nivel superior de intranet. Los más comunes como .com, .org y similares funcionan. No estoy interesado en crear una expresión regular para este asunto, por lo que se new URL(name).toURI()convierte en la solución.
Avec
59

Esta es la forma que probé y encontré útil,

URL u = new URL(name); // this would check for the protocol
u.toURI(); // does the extra checking required for validation of URI 
Prasanna Pilla
fuente
1
Buena. Usar solo una nueva URL (nombre) acepta casi todo. La url.toURI (); es exactamente lo que busca el desarrollador, ¡sin usar otras bibliotecas / marcos!
justastefan
2
Esto tampoco funcionará para URL con formato incorrecto, como http: /google.com. Usé UrlValidator de Apache Commons.
starf
1
Este es realmente peligroso. Veo que hay muchos otros artículos con este ejemplo. URL u = new URL(http://google).toURI();no lanzará una excepción.
Sonu Oommen
@SonuOommen tal vez porque new URL(http://google)es válido ^^ tenemos muchos dominios internos en mi empresa como este
user43968
8

Me encantaría publicar esto como un comentario a la respuesta de Tendayi Mawushe , pero me temo que no hay suficiente espacio;)

Esta es la parte relevante de la fuente de 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;

Puede construir fácilmente su propio validador desde allí.

usuario123444555621
fuente
6

La forma más "infalible" es comprobar la disponibilidad de la URL:

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

Mi enfoque favorito, sin bibliotecas externas:

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
fuente
3

A juzgar por el código fuente de URIla

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

El constructor realiza más validaciones que los otros constructores. Podrías probar ese, pero YMMV.

uckelman
fuente
3

No me gustó ninguna de las implementaciones (porque usan una Regex que es una operación costosa, o una biblioteca que es una exageración si solo necesita un método), así que terminé usando la clase java.net.URI con algunos comprobaciones adicionales y limitando los protocolos a: http, https, file, ftp, mailto, news, urn.

Y sí, detectar excepciones puede ser una operación costosa, pero probablemente no tan mala como las expresiones regulares:

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
fuente
2

paquete validador:

Parece haber un buen paquete de Yonatan Matalon llamado UrlUtil . Citando su API:

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

Enfoque de Sun: verifique la dirección de red

El sitio Java de Sun ofrece un intento de conexión como una solución para validar URL.

Otros fragmentos de código de expresiones regulares:

Hay intentos de validación de expresiones regulares en el sitio de Oracle y weberdev.com .

Adam Matan
fuente
1
Ese código es para verificar enlaces, que es un problema diferente. Esta pregunta tiene que ver con la validez de la URL, no si se puede establecer una conexión con ella.
Michael Myers
Este ejemplo trata de comprobar si la URL está disponible, no si está bien formada.
uckelman
De acuerdo, agregó otros enfoques.
Adam Matan