我正在使用com.sun.net.httpserver
中的简单Http服务器,如simple HTTP server in Java using only Java SE API中所述。
一切正常,但我不确定如果我不再需要它,我怎么能干净地关闭服务器。我不想在服务器仍在为某些请求发送数据时停止服务器,只有在它处于空闲状态时才会停止。
我的特定场景是执行OAuth舞蹈的桌面应用程序。我使用应用程序中嵌入的本地Web服务器来提供回调响应,应用程序启动桌面浏览器以使用java.awt.Desktop.browse
API显示服务器响应。
在我将响应页面写入HttpServer.stop(0)
响应输出流后,我尝试直接从我的HttpHandler.handle
函数调用HttpExchange
,但这太早了,浏览器显示{ {1}}。
当我的主应用程序完成其工作后停止服务器时会发生同样的情况 - 这通常为时过早,ERR_EMPTY_RESPONSE
尚未完成将数据发送出去。
我可以提供几秒延迟值来停止,但我希望实现正确和干净的同步。
对此有什么合适的解决方案?
答案 0 :(得分:2)
我可以根据一个CountDownLatch
+自定义ExecutorService
提供解决方案,该解决方案设置为HttpServer
的执行者:
public void runServer() throws Exception {
final ExecutorService ex = Executors.newSingleThreadExecutor();
final CountDownLatch c = new CountDownLatch(1);
HttpServer server = HttpServer.create(new InetSocketAddress(8888), 0);
server.createContext("/test", (HttpExchange h) -> {
StringBuilder resp = new StringBuilder();
for (int i = 0; i < 1_000_000; i++)
resp.append(i).append(", ");
String response = resp.toString();
h.sendResponseHeaders(200, response.length());
OutputStream os = h.getResponseBody();
os.write(response.getBytes());
os.close();
c.countDown(); // count down, letting `c.await()` to return
});
server.setExecutor(ex); // set up a custom executor for the server
server.start(); // start the server
System.out.println("HTTP server started");
c.await(); // wait until `c.countDown()` is invoked
ex.shutdown(); // send shutdown command to executor
// wait until all tasks complete (i. e. all responses are sent)
ex.awaitTermination(1, TimeUnit.HOURS);
server.stop(0);
System.out.println("HTTP server stopped");
}
我在我们的工作网络环境中对此进行了测试,它似乎正常工作。 HttpServer
不早于响应完全发送,所以我认为这正是您所需要的。
另一种方法可能不是关闭执行程序ex
,而是在将响应写入流后向其发送包含server.stop()
的新任务。由于ex
是单线程构造的,因此这个任务将在不早于先前任务完成的情况下执行,即。即响应已完全发送:
public void run() throws Exception {
final ExecutorService ex = Executors.newSingleThreadExecutor();
final HttpServer server = HttpServer.create(new InetSocketAddress(8888), 0);
server.createContext("/test", (HttpExchange h) -> {
// ... generate and write a response
ex.submit(() -> {
server.stop(0);
System.out.println("HTTP server stopped");
});
});
server.setExecutor(ex);
server.start();
System.out.println("HTTP server started");
}
有关详细信息,请参阅ExecutorService
答案 1 :(得分:0)
旧帖子,但我想为其他感兴趣的人推荐一个替代方法。我了解您要关闭服务器,但是您确实需要关闭服务器吗?仅仅不接受请求就足够了吗?
我正在处理服务器作为另一个Java应用程序的一部分启动的情况。在处理程序中有一个标志,并在满足所需条件后立即对其进行更新,只需停止接受请求即可。这样,如果您希望在更新标志后接收请求,也可以向客户端发送一些有用的信息。