特定の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;
}
GET
リクエストだと思います。代わりにHEAD
を送信する方法はありますか?これは何の役にも立ちません(私がやりたいことをするのでしょうか?)
あなたはそうすることができます。別の実行可能な方法は、 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の実行中にHEADに対して HTTP 405エラー (つまり、利用できない、実装されていない、許可されていない)が返される可能性のある貧弱なWebアプリまたは自家製のサーバーを考慮する必要があります。完璧に動作します。ドメイン/ホストではなくリンク/リソースを検証する場合は、GETを使用する方が信頼性が高くなります。
私の場合、サーバーの可用性をテストするだけでは不十分です。URLをテストする必要があります(webappがデプロイされない場合があります)
実際、ホストを接続しても、ホストが利用可能かどうかだけが通知され、コンテンツが利用可能かどうかは通知されません。ウェブサーバーは問題なく起動したが、サーバーの起動中にwebappがデプロイに失敗したことはよく起こります。ただし、これにより通常、サーバー全体がダウンすることはありません。 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セクション1 を参照してください。応答データを決定する場合、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を使用する代わりに、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();
}
}
同様の質問も確認してください RLが存在するか、Javaで404を返すかどうかを確認する方法
お役に立てれば。
HttpURLConnection を使用することもできます。これにより、要求メソッドを設定できます(たとえば、HEADに)。 ここに例があります これは、リクエストの送信、レスポンスの読み取り、切断の方法を示しています。
次のコードは、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;
}
}
ここ 作家はこれを提案します:
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;
}
考えられる質問
リンクを読んでください。それはとても良いようです
編集:それを使用する私の経験では、この方法ほど速くありません:
public boolean isOnline() {
NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
return netInfo != null && netInfo.isConnectedOrConnecting();
}
それらは少し異なりますが、インターネットへの接続を確認するだけの機能では、接続変数のために最初の方法が遅くなる場合があります。
Restletフレームワークの使用を検討してください。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によって示されたシナリオです-(HttpURLConnection)にキャストし、.disconnect()を呼び出します。