170 votes

Préféré le moyen de Java de ping une HTTP Url pour voir la disponibilité

J'ai besoin d'un moniteur de classe qui vérifie régulièrement si une URL HTTP est disponible. Je peux prendre soin de la "régulièrement" de la partie en utilisant le Printemps TaskExecutor l'abstraction, ce qui n'est pas le sujet ici. La Question est: Quelle est la meilleure façon de ping une adresse URL en java?

Voici mon code actuel comme point de 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;
}
  1. Est-ce tout de bon à tous (il va faire ce que je veux?)
  2. Dois-je en quelque sorte fermer la connexion?
  3. Je suppose que c'est une requête GET. Est-il possible d'envoyer la TÊTE à la place?

286voto

BalusC Points 498232

Est-ce tout de bon à tous (il va faire ce que je veux?)

Vous pouvez le faire. Un autre moyen est d'utiliser java.net.Socket.

Socket socket = null;
boolean reachable = false;
try {
    socket = new Socket(hostnameOrIP, 80);
    reachable = true;
} finally {            
    if (socket != null) try { socket.close(); } catch(IOException e) {}
}

Il y a aussi le InetAddress#isReachable():

boolean reachable = InetAddress.getByName(hostname).isReachable();

Toutefois, cela n'est pas explicitement tester le port 80. On risque d'obtenir des faux négatifs en raison d'un Pare-feu qui bloque les autres ports.


Dois-je en quelque sorte fermer la connexion?

Non, vous n'avez pas explicitement le besoin. Il est géré et mis en commun sous le capot.


Je suppose que c'est une requête GET. Est-il possible d'envoyer la TÊTE à la place?

Vous pouvez lancer le obtenue URLConnection de HttpURLConnection , puis utiliser setRequestMethod() pour définir la méthode de la requête. Cependant, vous devez prendre en compte que certains pauvres webapps ou endogène serveurs peuvent revenir erreur HTTP 405 pour une TÊTE (c'est à dire pas disponible, pas mis en œuvre, ne sont pas permis) alors qu'un GET fonctionne parfaitement bien. Mais, ce sont là de très rares cas.


Mise à jour selon les commentaires: connexion de l'hôte informe seulement si l'hôte est disponible, pas si le contenu est disponible. Vous semblez plus intéressé par le contenu, car il peut aussi bien arriver que le serveur a démarré sans problèmes, mais la webapp impossible de déployer au cours du serveur de démarrer. Ce sera toutefois généralement pas en cause l'intégralité de l'arrêt du serveur. Si vous souhaitez déterminer le code de réponse HTTP.

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 le statut de la réponse codes de voir la RFC 2616 section 10. Appelant connect() n'est d'ailleurs pas nécessaire si vous êtes à la détermination des données de réponse. Il sera implicitement se connecter.

Pour référence, voici un exemple complet dans la saveur d'une méthode utilitaire, en prenant aussi en compte avec des délais d'expiration:

/**
 * 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 ping(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;
    }
}

18voto

YoK Points 8221

Au lieu d'utiliser URLConnection utilisation HttpURLConnection en appelant openConnection() sur votre URL de l'objet.

Ensuite, utilisez getResponseCode() vous donnera la réponse HTTP une fois que vous avez lu à partir de 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 même question http://stackoverflow.com/questions/1378199/how-to-check-if-a-url-exists-or-returns-404-with-java

Espérons que cette aide.

8voto

Bill the Lizard Points 147311

Vous pouvez également utiliser HttpURLConnection, qui vous permet d’établir la méthode de demande (à la tête par exemple). Voici un exemple qui montre comment envoyer une demande, lire la réponse et déconnecter.

2voto

Avi Flax Points 14898

Envisagez d’utiliser le framework Restlet, qui possède une sémantique grande pour ce genre de chose. Il est puissant et souple.

Le code pourrait être aussi simple que :

0voto

bartolomeo_n Points 41

wrt 2.: vous feriez mieux de la fermer. Cependant, il peut varier en fonction de la mise en œuvre de URLConnection qui est utilisé. J'ai juste fini de traquer une fuite de ressources dans notre système, tout simplement parce que de cela. Une application a généré beaucoup de pendaison de connexions (selon lsof; nous sommes en cours d'exécution sur JDK1.6) et la raison en est que nous avons utilisé exactement le morceau de code que vous avez indiqué. Les Connexions TCP n'ont pas été fermées ni par ex. retourné à la piscine, etc. - ils ont été laissés dans ESTABILISHED état. Dans ce cas précis, le scénario est illustré par YoK - cast (HttpURLConnection) et appeler .disconnect().

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X