J’ai besoin d’une classe de moniteur qui vérifie régulièrement si une URL HTTP donnée est disponible. Je peux prendre soin de la partie “régulièrement” en utilisant l’abstraction Spring TaskExecutor, ce n’est donc pas le sujet ici. La question est la suivante: quelle est la meilleure façon de faire un ping sur une URL dans java?
Voici mon code actuel comme sharepoint départ:
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
. Y a-t-il un moyen d’envoyer HEAD
place? Est-ce que c’est bon (fera-t-il ce que je veux?)
Vous pouvez le faire. Un autre moyen possible est d’utiliser java.net.Socket
.
public static boolean pingHost(Ssortingng 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. } }
Il y a aussi le InetAddress#isReachable()
:
boolean reachable = InetAddress.getByName(hostname).isReachable();
Cela ne teste cependant pas explicitement le port 80. Vous risquez d’obtenir des faux négatifs en raison d’un blocage du pare-feu par d’autres pare-feu.
Dois-je en quelque sorte fermer la connexion?
Non, vous n’avez pas explicitement besoin Il est manipulé et mis en commun sous les capots.
Je suppose que c’est une requête GET. Y a-t-il un moyen d’envoyer HEAD à la place?
Vous pouvez URLConnection
obtenue en HttpURLConnection
, puis utiliser setRequestMethod()
pour définir la méthode de requête. Cependant, vous devez tenir compte du fait que certaines applications Web médiocres ou certains serveurs Web peuvent renvoyer une erreur HTTP 405 pour un HEAD (c.-à-d. Non disponible, non implémenté, non autorisé) alors qu’un GET fonctionne parfaitement. L’utilisation de GET est plus fiable si vous souhaitez vérifier les liens / ressources et non les domaines / hôtes.
Test du serveur pour la disponibilité ne suffit pas dans mon cas, je dois tester l’URL (l’application Web peut ne pas être déployée)
En effet, la connexion d’un hôte n’informe que si l’hôte est disponible, pas si le contenu est disponible. Il peut arriver qu’un serveur Web ait démarré sans problème, mais que l’application Web ne se soit pas déployée au démarrage du serveur. Cela ne provoquera cependant généralement pas la panne du serveur entier. Vous pouvez déterminer cela en vérifiant si le code de réponse HTTP est 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
Pour plus de détails sur les codes d'état de réponse, voir RFC 2616 section 10 . L'appel de connect()
n'est par ailleurs pas nécessaire si vous déterminez les données de réponse. Il se connectera implicitement.
Pour référence ultérieure, voici un exemple complet de la saveur d'une méthode utilitaire, prenant également en compte les délais d'attente:
/** * Pings a HTTP URL. This effectively sends a HEAD request and returns
true
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. * @returntrue
if the given HTTP URL has returned response code 200-399 on a HEAD request within the * given timeout, otherwisefalse
. */ public static boolean pingURL(Ssortingng url, int timeout) { url = url.replaceFirst("^https", "http"); // Otherwise an exception may be thrown on invalid SSL certificatees. 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; } }
Au lieu d’utiliser URLConnection, utilisez HttpURLConnection en appelant openConnection () sur votre object URL.
Ensuite, utilisez getResponseCode () pour obtenir la réponse HTTP une fois que vous avez lu la connexion.
voici le code:
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(); } }
Vérifiez également la question similaire Comment vérifier si une URL existe ou retourne 404 avec Java?
J’espère que cela t’aides.
Vous pouvez également utiliser HttpURLConnection , qui vous permet de définir la méthode de requête (par exemple HEAD). Voici un exemple qui montre comment envoyer une demande, lire la réponse et se déconnecter.
Le code suivant exécute une requête HEAD
pour vérifier si le site Web est disponible ou non.
public static boolean isReachable(Ssortingng 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; } }
ici l’auteur suggère ceci:
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; }
Questions possibles
lisez le lien. sa semble très bien
EDIT: dans mon exp d’utiliser ce n’est pas aussi rapide que cette méthode:
public boolean isOnline() { NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo(); return netInfo != null && netInfo.isConnectedOrConnecting(); }
ils sont un peu différents mais dans la fonctionnalité de vérification de la connexion à Internet, la première méthode peut devenir lente en raison des variables de connexion.
Pensez à utiliser le framework Restlet, qui a une grande sémantique pour ce genre de chose. C’est puissant et flexible.
Le code pourrait être aussi simple que:
Client client = new Client(Protocol.HTTP); Response response = client.get(url); if (response.getStatus().isError()) { // uh oh! }
vers 2: vous feriez mieux de le fermer. Cependant, cela peut dépendre de l’implémentation particulière d’URLConnection utilisée. Je viens de terminer la recherche d’une fuite de ressources dans notre système à cause de cela. Une application a généré beaucoup de connexions suspendues (selon lsof; nous l’exécutons sur JDK1.6) et la raison en est que nous avons utilisé exactement le morceau de code que vous avez montré. Les connexions TCP n’ont pas été fermées, par exemple retournées au pool, etc. – elles ont été laissées dans l’état ESTABILISHED. Dans ce cas, le scénario approprié est celui affiché par YoK – convertissez-le en (HttpURLConnection) et appelez .disconnect ().