Como verificar se há um URL válido em Java?

92

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

Se tentou ligar new URL(urlString)e pegar um MalformedURLException, mas parece estar feliz com qualquer coisa que comece 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 um regex?

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

Eric Wilson
fonte
Como você define a validade se não vai estabelecer uma conexão?
Michael Myers
2
Você pode dar um exemplo de algo que não é um URL válido que o URLconstrutor aceita?
uckelman
1
@mmyers: A validade deve ser determinada pelas RFCs 2396 e 2732, aquelas que definem o que é um URL.
uckelman
4
@uckelman: Quase tudo. " http://***" funciona. " http://my favorite site!" funciona. Não consigo fazer uma exceção (quando http: // está no início)
Eric Wilson
2
possível duplicata do URL
JasonB

Respostas:

100

Considere o uso da classe Apache Commons UrlValidator

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

Existem várias propriedades que você pode definir para controlar a forma como este se comporta de classe, por padrão http, httpse ftpsão aceitos.

Tendayi Mawushe
fonte
7
parece não funcionar com domínios mais novos, como .london etc
VH
que tal urls de intranet?
Puneet,
Ele não valida urls com sublinhados.
Udit Kumawat
Não funciona com novos TLDs e nomes de domínio locais, por exemplo local, etc.
Não consegui fazer com que o UrlValidator funcionasse com nosso domínio de nível superior da intranet estranha. Os mais comuns, como .com, .org e outros semelhantes. Não estou interessado em criar um RegExp para esse assunto, então ele new URL(name).toURI()se tornou a solução.
Avec
59

Esta é a maneira que experimentei 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 
Prasanna Pilla
fonte
1
Um bom. Usar apenas um novo URL (nome) aceita quase tudo. O url.toURI (); é exatamente o que o desenvolvedor está procurando - sem usar outras bibliotecas / frameworks!
justastefan
2
Isso também não funcionará com URLs malformados, como http: /google.com. Eu usei o UrlValidator do Apache Commons.
starf
1
Este é realmente perigoso. Vejo que há muitos outros artigos por aí com este exemplo. URL u = new URL(http://google).toURI();não lançará uma exceção.
Sonu Oommen de
@SonuOommen talvez porque new URL(http://google)seja válido ^^ temos muitos domínios internos em minha empresa como este
user43968
8

Eu adoraria postar isso como um comentário à resposta de Tendayi Mawushe , mas infelizmente não há espaço suficiente;)

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

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

user123444555621
fonte
6

A maneira mais "infalível" é verificar a disponibilidade do URL:

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

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) {
}
Andrei Volgin
fonte
3

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

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

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

uckelman
fonte
3

Eu não gostei de nenhuma das implementações (porque eles usam um Regex que é uma operação cara, ou uma biblioteca que é um exagero se você só precisa de um método), então acabei usando a classe java.net.URI com alguns verificações extras e limitar os protocolos a: http, https, file, ftp, mailto, news, urn.

E sim, detectar exceções pode ser uma operação cara, mas provavelmente não tão ruim quanto as expressões 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
fonte
2

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 tentativa de conexão como uma solução para validação de URLs.

Outros snippets de código regex:

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

Adam Matan
fonte
1
Esse código é para verificar links, o que é um problema diferente. Esta questão é sobre a validade do URL, não se uma conexão pode ser estabelecida com ele.
Michael Myers
Este exemplo é sobre como verificar se o URL está disponível, não se está bem formado.
uckelman
Concordo, acrescentou outras abordagens.
Adam Matan