167

特定の HTTP URL が使用可能かどうかを定期的にチェックするモニター クラスが必要です。Spring TaskExecutor 抽象化を使用して「定期的に」部分を処理できるので、それはここでは取り上げません。質問は次のとおりです。Java で URL を ping するための推奨される方法は何ですか?

出発点としての私の現在のコードは次のとおりです。

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代わりに送信する方法はありますか?
4

6 に答える 6

282

これはまったく良いですか(それは私が望むことをしますか?)

あなたはそうすることができます。別の実行可能な方法は、を使用すること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リクエストだと思います。代わりに HEAD を送信する方法はありますか?

URLConnection取得した を にキャストしHttpURLConnection、それを使用setRequestMethod()してリクエスト メソッドを設定できます。ただし、GET が完全に正常に機能しているのに、貧弱な webapps または自家製サーバーが HEAD に対してHTTP 405 エラー(つまり、利用できない、実装されていない、許可されていない) を返す可能性があることを考慮する必要があります。ドメイン/ホストではなくリンク/リソースを検証する場合は、GET を使用する方が信頼性が高くなります。


私の場合、サーバーの可用性をテストするだけでは不十分です。URL をテストする必要があります (Web アプリケーションがデプロイされていない可能性があります)。

実際、ホストを接続しても、コンテンツが利用可能かどうかではなく、ホストが利用可能かどうかのみが通知されます。Web サーバーが問題なく起動したにもかかわらず、サーバーの起動中に Web アプリケーションの展開に失敗したということもあり得ます。ただし、通常、これによってサーバー全体がダウンすることはありません。これは、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;
    }
}
于 2010-08-27T12:56:41.610 に答える
17

URLConnection を使用する代わりに、URL オブジェクトで openConnection() を呼び出してHttpURLConnectionを使用します。

次に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が存在するか、Javaで404を返すかを確認するにはどうすればよいですか?

お役に立てれば。

于 2010-08-27T13:00:04.410 に答える
8

を使用することもHttpURLConnectionできます。これにより、リクエスト メソッドを設定できます (HEADたとえば、に)。 リクエストを送信し、レスポンスを読み取り、切断する方法を示す例を次に示します。

于 2010-08-27T12:48:15.777 に答える
4

次のコードはHEAD、Web サイトが利用可能かどうかを確認するリクエストを実行します。

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;
    }
}
于 2015-04-04T14:37:59.700 に答える
2

この種のことに対して優れたセマンティクスを持つ Restlet フレームワークの使用を検討してください。パワフルで柔軟です。

コードは次のように単純です。

Client client = new Client(Protocol.HTTP);
Response response = client.get(url);
if (response.getStatus().isError()) {
    // uh oh!
}
于 2010-08-27T13:36:55.660 に答える