首选的Java方法来ping HTTP URL的可用性

我需要一个监视器类来定期检查给定的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; } 
  1. 这有什么好处(它会做我想要的)?
  2. 我必须以某种方式closures连接吗?
  3. 我想这是一个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(); 

但是,这并没有明确地testing端口80.由于防火墙阻塞了其他端口,您可能会冒风险。


我必须以某种方式closures连接吗?

不,你没有明确的需要。 它的处理和汇集在引擎盖下。


我想这是一个GET请求。 有没有办法发送HEAD呢?

您可以将获取的URLConnectionHttpURLConnection ,然后使用setRequestMethod()设置请求方法。 然而,你需要考虑到一些可怜的webapps或自行开发的服务器可能会返回一个HEAD HTTP 405错误 (即不可用,未实现,不允许),而GET工作完全正常。 如果您打算validation链接/资源而不是域/主机,则使用GET更可靠。


在我的情况下testing服务器的可用性是不够的,我需要testing的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; } } 

通过调用URL对象上的openConnection(),而不是使用URLConnection来使用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是否存在或返回404与Java?

希望这可以帮助。

您也可以使用HttpURLConnection ,它允许您设置请求方法(以HEAD为例)。 以下是一个示例 ,显示如何发送请求,读取响应以及断开连接。

以下代码执行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; } } 

考虑使用Restlet框架,这种框架具有很好的语义。 它强大而灵活。

代码可以像下面这样简单:

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

2:你最好closures它。 但是,这可能取决于所使用的URLConnection的具体实现。 我刚刚完成跟踪我们系统中的资源泄漏。 一个应用程序产生了很多挂起的连接(根据lsof;我们正在JDK1.6上运行),原因是我们已经使用了你已经显示的代码段。 TCP连接没有closures,例如返回到游泳池等 – 他们被留在ESTABILISHED状态。 在这种情况下,正确的场景是YoK显示的场景 – 将其转换为(HttpURLConnection)并调用.disconnect()。

这里作者提出这样的build议:

 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我自己的网页,我想要求吗? 当然! 你甚至可以检查两者,如果你想区分“可用的互联网连接”和你自己的服务器beeing可达如果DNS是宕机? Google DNS(例如8.8.8.8)是全球最大的公共DNS服务。 截至2013年,它每天提供1300亿个请求。 让我们只是说,你的应用程序没有回应可能不是今天的谈话。

阅读链接。 它看起来非常好

编辑:在我的使用它的exp,它不像这种方法一样快:

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

他们有点不同,但在检查连接到互联网的function,第一种方法可能会变慢由于连接variables。