首选java方式ping http url以获得可用性

wlsrxk51  于 2021-08-20  发布在  Java
关注(0)|答案(6)|浏览(714)

我需要一个监视器类,它定期检查给定的http url是否可用。我可以使用spring taskexecutor抽象处理“定期”部分,所以这不是本文的主题。问题是:在java中ping url的首选方式是什么?
以下是我当前的代码作为起点:

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 相反

bakd9h0s

bakd9h0s1#

这有什么好处吗(它能满足我的需要吗?)
你可以这样做。另一个可行的方法是使用 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?
你可以投下这个球 URLConnectionHttpURLConnection 然后使用 setRequestMethod() 设置请求方法。但是,您需要考虑到,当get工作正常时,一些糟糕的Web应用程序或自制服务器可能会返回http 405 head错误(即不可用、未实现、不允许)。如果您打算验证链接/资源而不是域/主机,那么使用get更可靠。
测试服务器的可用性是不够的,在我的情况下,我需要测试url(可能没有部署webapp)
实际上,连接主机只会通知主机是否可用,而不会通知内容是否可用。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;
    }
}
kkih6yb8

kkih6yb82#

不要使用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();
        }
    }

还要检查类似的问题:如何使用java检查url是否存在或返回404?
希望这有帮助。

u59ebvdq

u59ebvdq3#

您还可以使用httpurlconnection,它允许您设置请求方法(例如,设置为head)。下面的示例演示了如何发送请求、读取响应和断开连接。

ttp71kqs

ttp71kqs4#

下面的代码执行 HEAD 请求检查网站是否可用。

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;
    }
}
yhxst69z

yhxst69z5#

在这里,作者建议:

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;
}

可能的问题
这真的够快吗?是的,非常快!
我能不能只ping我自己的页面,不管怎样我都想请求它?当然你甚至可以检查两者,如果你想区分“互联网连接可用”和你自己的服务器可访问,如果dns关闭了怎么办?谷歌dns(例如8.8.8.8)是世界上最大的公共dns服务。截至2013年,它每天处理1300亿个请求。比方说,你的应用程序没有响应可能不是今天的热门主题。
阅读链接。它看起来很好
编辑:在我使用它的经验中,它不如此方法快:

public boolean isOnline() {
    NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
    return netInfo != null && netInfo.isConnectedOrConnecting();
}

它们有点不同,但由于连接变量的原因,第一种方法仅用于检查与internet的连接的功能可能会变慢。

zynd9foi

zynd9foi6#

考虑使用RestLeT框架,它对于这类事情具有很强的语义。它的强大和灵活。
代码可以简单到:

Client client = new Client(Protocol.HTTP);
Response response = client.get(url);
if (response.getStatus().isError()) {
    // uh oh!
}

相关问题