Предпочтительный способ проверки связи HTTP с URL-адресом для проверки доступности

Мне нужен класс монитора, который регулярно проверяет, доступен ли данный HTTP-URL. Я могу позаботиться о «регулярной» части, используя абстракцию 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;
}
  1. Это вообще хорошо (будет ли это то, что я хочу)?
  2. Должен ли я каким-то образом закрыть соединение?
  3. Я полагаю, что это GET запрос. Можно ли вместо этого отправить HEAD ?
157
задан blacktide 9 June 2016 в 22:30
поделиться

3 ответа

Хорошо ли это вообще (будет ли это делать то, что я хочу?)

Вы можете сделать это. Другой возможный способ — использовать java.net.Розетка.

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-запрос. Есть ли способ вместо этого отправить HEAD?

Вы можете преобразовать полученный URLConnection в HttpURLConnection , а затем использовать setRequestMethod() , чтобы установить метод запроса. Однако вам необходимо принять во внимание, что некоторые плохие веб-приложения или собственные серверы могут возвращать ошибку HTTP 405 для HEAD (т. е. недоступны, не реализованы, не разрешены), в то время как 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;
    }
}
261
ответ дан 23 November 2019 в 21:45
поделиться

Рассмотрите возможность использования инфраструктуры Restlet, которая имеет отличную семантику для такого рода вещей. Он мощный и гибкий.

Код может быть таким простым, как:

Client client = new Client(Protocol.HTTP);
Response response = client.get(url);
if (response.getStatus().isError()) {
    // uh oh!
}
2
ответ дан 23 November 2019 в 21:45
поделиться

Вместо использования 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?

Надеюсь, это поможет.

17
ответ дан 23 November 2019 в 21:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: