Como procurar por um URL válido em Java?

Qual é a melhor maneira de verificar se um URL é válido em Java?

Se tentou chamar new URL(urlString) e pegar um MalformedURLException , mas parece estar feliz com qualquer coisa que comece com http:// .

Não estou preocupado em estabelecer uma conexão, apenas validade. Existe um método para isso? Uma anotação no Hibernate Validator? Devo usar uma regex?

Edit: Alguns exemplos de URLs aceitos são http://*** e http://my favorite site! .

Considere usar a class Apache Commons UrlValidator

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

Existem várias propriedades que você pode definir para controlar como essa class se comporta; por padrão, http , https e ftp são aceitos.

Aqui está a maneira que eu tentei e achei útil,

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

Eu adoraria postar isso como um comentário para a resposta de Tendayi Mawushe , mas temo que não haja espaço suficiente;)

Esta é a parte relevante da fonte 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; 

Você pode facilmente construir seu próprio validador a partir daí.

Minha abordagem favorita, sem 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) { } 

pacote validador:

Parece haver um bom pacote de Yonatan Matalon chamado UrlUtil . Citando sua API:

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

Abordagem da Sun – verifique o endereço de rede

O site Java da Sun oferece uma tentativa de conexão como uma solução para validação de URLs.

Outros trechos de código regex:

Existem tentativas de validação de regex no site da Oracle e no weberdev.com .

A julgar pelo código-fonte do URI , o

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

construtor faz mais validação do que os outros construtores. Você pode tentar isso, mas YMMV.

Eu não gostei de nenhuma das implementações (porque elas usam um Regex que é uma operação cara, ou uma biblioteca que é um exagero se você precisar apenas de um método), então eu acabei usando a class java.net.URI com algum verificações extras e limitar os protocolos a: http, https, arquivo, ftp, mailto, news, urn.

E sim, capturar exceções pode ser uma operação cara, mas provavelmente não tão ruim quanto as Expressões 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; }