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

96

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

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

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

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

Эрик Уилсон
источник
Как вы определяете действительность, если вы не собираетесь устанавливать соединение?
Майкл Майерс
2
Вы можете привести пример того, что не является допустимым URL-адресом, который URLпринимает конструктор?
uckelman
1
@mmyers: Срок действия должен определяться RFC 2396 и 2732, которые определяют, что такое URL.
uckelman
4
@uckelman: Да что угодно. " http://***" работает. " http://my favorite site!" работает. Я не могу заставить его генерировать исключение (когда http: // находится в начале.)
Эрик Уилсон,
2
возможный дубликат Validating URL в Java
JasonB

Ответы:

102

Рассмотрите возможность использования класса Apache Commons UrlValidator

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

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

Тендаи Мавуше
источник
7
похоже, он не работает с новыми доменами, такими как .london и т. д.
VH
как насчет URL-адресов интрасети?
Puneet
Он не проверяет URL-адреса с подчеркиванием.
Удит Кумават 02
Не работает с новыми TLD и локальными доменными именами, например local, и т. Д.
Мне не удалось заставить UrlValidator работать с нашим странным доменом верхнего уровня в интрасети. Обычные, такие как .com, .org и тому подобное, работают. Я не заинтересован в создании RegExp для этого вопроса, поэтому он new URL(name).toURI()стал решением.
Avec
60

Вот способ, который я пробовал и нашел полезным:

URL u = new URL(name); // this would check for the protocol
u.toURI(); // does the extra checking required for validation of URI 
Прасанна Пилла
источник
1
Хороший. Использование только нового URL-адреса (имени) позволяет принимать почти все. Url.toURI (); это именно то, что ищет разработчик - без использования других библиотек / фреймворков!
Justastefan
2
Это также не будет работать с искаженными URL-адресами, такими как http: /google.com. Я использовал UrlValidator от Apache Commons.
starf
1
Это действительно опасно. Я вижу, что есть много других статей с этим примером. URL u = new URL(http://google).toURI();не вызовет исключения.
Sonu Oommen
1
@SonuOommen, возможно, потому, что new URL(http://google)он действителен ^^ у нас в компании много таких внутренних доменов
user43968
8

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

Это соответствующая часть из источника 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;

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

user123444555621
источник
6

Самый «надежный» способ - проверить доступность URL:

public boolean isURL(String url) {
  try {
     (new java.net.URL(url)).openStream().close();
     return true;
  } catch (Exception ex) { }
  return false;
}
Джо
источник
5

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

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) {
}
Андрей Волгин
источник
3

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

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

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

Uckelman
источник
3

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

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

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
источник
2

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

Кажется, есть хороший пакет от Йонатана Маталона под названием 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 предпринимаются попытки проверки регулярных выражений .

Адам Матан
источник
1
Этот код предназначен для проверки ссылок, а это другая проблема. Это вопрос о действительности URL-адреса, а не о том, можно ли к нему установить соединение.
Майкл Майерс
В этом примере проверяется, доступен ли URL-адрес, а не правильно ли он сформирован.
uckelman
Согласились, добавили другие подходы.
Адам Матан,