Как проверить действительный URL-адрес в Java?

Каков наилучший способ проверить, действительно ли URL-адрес в Java?

Если попытался вызвать new URL(urlString) и поймать MalformedURLException, но он, похоже, доволен тем, что начинается с http://.

Меня не интересует установление соединения, просто действительность. Есть ли способ для этого? Аннотации в Hibernate Validator? Должен ли я использовать регулярное выражение?

Изменить: Некоторые примеры принятых URL-адресов: http://*** и http://my favorite site!.

Ответ 1

С помощью Apache Commons UrlValidator class

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

Существует несколько свойств, которые вы можете настроить для управления тем, как ведет себя этот класс, по умолчанию http, https и ftp.

Ответ 2

Вот как я пытался и нашел полезным,

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

Ответ 3

Я бы хотел опубликовать это как комментарий к ответ Тендайи Маушу, но я боюсь, что не хватает места;)

Это важная часть из 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;

Вы можете легко создать свой собственный валидатор.

Ответ 4

Мой любимый подход, без внешних библиотек:

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

Ответ 5

пакет проверки:

Кажется, что хороший пакет Yonatan Matalon назвал UrlUtil. Указание его API:

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

Подход Sun - проверьте сетевой адрес

Сайт Sun Java предлагает подключить попытку в качестве решения для проверки URL-адресов.

Другие фрагменты кода регулярного выражения:

Существуют попытки проверки регулярных выражений на сайт Oracle и weberdev.com.

Ответ 6

Судя по исходному коду для URI,

public URL(URL context, String spec, URLStreamHandler handler)
Конструктор

делает большую проверку, чем другие конструкторы. Вы можете попробовать это, но YMMV.

Ответ 7

Самый "надежный" способ - проверить наличие URL:

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

Ответ 8

Мне не понравилась ни одна из реализаций (потому что они используют Regex, что является дорогостоящей операцией, или библиотекой, которая является излишним, если вам нужен только один метод), поэтому я закончил использование java.net.URI класс с некоторыми дополнительными проверками и ограничение протоколов: http, https, file, ftp, mailto, news, urn.

И да, исключение catching может быть дорогостоящей операцией, но, вероятно, не так плохо, как регулярные выражения:

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;
}