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

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

Si intentas llamar a una new URL(urlString) y atrapar una excepción MalformedURLException , parece estar contento con cualquier cosa que comience con http:// .

No me preocupa establecer una conexión, solo validez. ¿Hay un método para esto? Una anotación en Hibernate Validator? ¿Debo usar una expresión regular?

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

Considere usar la clase Apache Commons UrlValidator

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

Hay varias propiedades que puede configurar para controlar cómo se comporta esta clase, por defecto http , https y ftp son aceptados.

Aquí es la forma en que lo intenté 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 

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 UrlValidator de 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; 

Usted puede construir fácilmente su propio validador desde allí.

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

paquete de validador:

Parece que hay 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. 

El enfoque de Sun: verifique la dirección de red

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

Otros fragmentos de código regex:

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

A juzgar por el código fuente de URI , el

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

constructor hace más validación que los otros constructores. Puede probar ese, pero YMMV.

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

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

 final static Set protocols, protocolsWithHost; static { protocolsWithHost = new HashSet( Arrays.asList( new String[]{ "file", "ftp", "http", "https" } ) ); protocols = new HashSet( 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; }