Предпочтительный способ Java для проверки доступности HTTP-URL
мне нужен класс монитора, который регулярно проверяет, доступен ли данный URL-адрес HTTP. Я могу позаботиться о" регулярной " части, используя абстракцию Spring TaskExecutor, так что это не тема здесь. Вопрос в том:каков предпочтительный способ пинга URL-адреса в java?
вот мой текущий код в качестве отправной точки:
try {
final URLConnection connection = new URL(url).openConnection();
connection.connect();
LOG.info("Service " + url + " available, yeah!");
available = true;
} catch (final MalformedURLException e) {
throw new IllegalStateException("Bad URL: " + url, e);
} catch (final IOException e) {
LOG.info("Service " + url + " unavailable, oh no!", e);
available = false;
}
- это вообще хорошо (будет ли он делать то, что я хочу)?
- я должен как-то закрыть связь?
- Я полагаю, что это
GET
запрос. Есть ли способ отправитьHEAD
вместо?
7 ответов:
это вообще хорошо (будет ли он делать то, что я хочу?)
вы можете это сделать. Другим возможным способом является использование
java.net.Socket
.public static boolean pingHost(String host, int port, int timeout) { try (Socket socket = new Socket()) { socket.connect(new InetSocketAddress(host, port), timeout); return true; } catch (IOException e) { return false; // Either timeout or unreachable or failed DNS lookup. } }
есть еще
InetAddress#isReachable()
:boolean reachable = InetAddress.getByName(hostname).isReachable();
однако это явно не тестирует порт 80. Вы рискуете получить ложные негативы из-за брандмауэра, блокирующего другие порты.
я должен как-то закрыть связь?
нет, вам явно не нужно. Он обработан и собран под капотами.
я полагаю, что это запрос GET. Есть ли способ отправить голову вместо этого?
вы можете бросить полученный
URLConnection
доHttpURLConnection
и затем использоватьsetRequestMethod()
для установки метода запроса. Однако вы должны учитывать, что некоторые плохие веб-приложения или доморощенные серверы могут возвратить ошибка HTTP 405 для головы (т. е. недоступно, не реализовано, не разрешено), в то время как GET работает отлично. Использование GET более надежно, если вы собираетесь проверять ссылки / ресурсы, а не Домены/хосты.
тестирование сервера на доступность недостаточно в моем случае, мне нужно проверить URL (веб-приложение не может быть развернуто)
действительно, подключение хоста только информирует, если хост доступен, нет, если контент доступен. Это может также хорошо случиться, что веб-сервер запустился без проблем, но веб-приложение не удалось развернуть во время запуска сервера. Однако это обычно не приводит к тому, что весь сервер отключается. Вы можете определить это, проверив, является ли код ответа HTTP 200.
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod("HEAD"); int responseCode = connection.getResponseCode(); if (responseCode != 200) { // Not OK. } // < 100 is undetermined. // 1nn is informal (shouldn't happen on a GET/HEAD) // 2nn is success // 3nn is redirect // 4nn is client error // 5nn is server error
для получения более подробной информации о кодах состояния ответа см. RFC 2616 раздел 10. Звоню
connect()
кстати, не требуется, если вы определяете данные ответа. Оно будет неявно подключения.для дальнейшего использования, вот полный пример в вкусе метода полезности, также принимая во внимание с таймаутами:
/** * Pings a HTTP URL. This effectively sends a HEAD request and returns <code>true</code> if the response code is in * the 200-399 range. * @param url The HTTP URL to be pinged. * @param timeout The timeout in millis for both the connection timeout and the response read timeout. Note that * the total timeout is effectively two times the given timeout. * @return <code>true</code> if the given HTTP URL has returned response code 200-399 on a HEAD request within the * given timeout, otherwise <code>false</code>. */ public static boolean pingURL(String url, int timeout) { url = url.replaceFirst("^https", "http"); // Otherwise an exception may be thrown on invalid SSL certificates. try { HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setConnectTimeout(timeout); connection.setReadTimeout(timeout); connection.setRequestMethod("HEAD"); int responseCode = connection.getResponseCode(); return (200 <= responseCode && responseCode <= 399); } catch (IOException exception) { return false; } }
вместо использования URLConnection используйте HttpURLConnection вызывая openConnection () на вашем объекте URL.
затем использовать getResponseCode() даст вам ответ HTTP, как только вы прочитали из соединения.
вот код:
HttpURLConnection connection = null; try { URL u = new URL("http://www.google.com/"); connection = (HttpURLConnection) u.openConnection(); connection.setRequestMethod("HEAD"); int code = connection.getResponseCode(); System.out.println("" + code); // You can determine on HTTP return code received. 200 is success. } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if (connection != null) { connection.disconnect(); } }
также проверьте аналогичный вопрос Как проверить, если URL существует или возвращает 404 с Java?
надеюсь, что это помогает.
вы также можете использовать HttpURLConnection, что позволяет установить метод запроса (например, HEAD). вот пример это показывает, как отправить запрос, прочитать ответ и отключить.
следующий код выполняет
HEAD
запрос на проверку доступности веб-сайта.public static boolean isReachable(String targetUrl) throws IOException { HttpURLConnection httpUrlConnection = (HttpURLConnection) new URL( targetUrl).openConnection(); httpUrlConnection.setRequestMethod("HEAD"); try { int responseCode = httpUrlConnection.getResponseCode(); return responseCode == HttpURLConnection.HTTP_OK; } catch (UnknownHostException noInternetConnection) { return false; } }
здесь автор предлагает следующее:
public boolean isOnline() { Runtime runtime = Runtime.getRuntime(); try { Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8"); int exitValue = ipProcess.waitFor(); return (exitValue == 0); } catch (IOException | InterruptedException e) { e.printStackTrace(); } return false; }
Возможные Вопросы
- это действительно достаточно быстро?Да, очень быстро!
- не мог бы я просто пинговать свою собственную страницу, которую я хочу чтобы запросить в любом случае? Конечно! Вы даже можете проверить оба, если хотите различайте "доступное подключение к интернету" и свое собственное серверы становятся доступными что делать, если DNS не работает? Google DNS (например 8.8.8.8) является крупнейшим публичным DNS-сервисом в мире. Как в 2013 году он обслуживает 130 миллиардов запросов в день. Давайте просто скажем, что ваше приложение нет ответ, вероятно, не был бы разговором дня.
читать по ссылке. это кажется очень хорошим
изменить: в моего опыта его использования, это не так быстро, как этот метод:
public boolean isOnline() { NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo(); return netInfo != null && netInfo.isConnectedOrConnecting(); }
они немного отличаются, но в функциональности для просто проверки подключения к интернету первый метод может стать медленным из-за переменных подключения.
рассмотрите возможность использования фреймворка Restlet, который имеет большую семантику для такого рода вещей. Он мощный и гибкий.
код может быть таким же простым, как:
Client client = new Client(Protocol.HTTP); Response response = client.get(url); if (response.getStatus().isError()) { // uh oh! }
wrt 2.- тебе лучше закрыть его. Однако, это может зависеть от конкретной реализации URLConnection, который используется. Я только что закончил отслеживать утечки ресурсов в нашей системе только из-за этого. Приложение сгенерировало множество висячих соединений (согласно lsof; мы запускаем его на JDK1.6), и причина в том, что мы использовали именно тот фрагмент кода, который вы показали. TCP-соединения не были закрыты, например, возвращены в пул и т. д. - они были оставлены в стабильном состоянии. В в этом случае правильный сценарий-это тот, который показан YoK-cast it to (HttpURLConnection) и invoke .разъединять.)(