java - 服务请求后停止 HttpServer

标签 java http httpserver

我正在使用来自 com.sun.net.httpserver 的简单 Http 服务器,如 simple HTTP server in Java using only Java SE API 中所述.

一切正常,但我不确定一旦我不再需要它时如何彻底关闭服务器。我不想在服务器仍在为某些请求发送数据时停止服务器,只有在它空闲时才停止。

我的特定场景是执行 OAuth 舞蹈的桌面应用程序。我使用应用程序中嵌入的本地 Web 服务器提供回调响应,应用程序启动桌面浏览器以使用 java.awt.Desktop.browse 显示服务器响应应用程序接口(interface)。

我试过调用HttpServer.stop(0)直接来 self 的 HttpHandler.handle函数,在我将响应页面写入 HttpExchange 之后响应输出流,但这还为时过早,浏览器显示 ERR_EMPTY_RESPONSE .

当我在主应用程序完成其工作后停止服务器时,也会发生同样的情况 - 这通常为时过早,HttpServer此时尚未完成数据发送。

我可以提供几秒的延迟值来停止,但我想实现正确且干净的同步。

什么是正确的解决方案?

最佳答案

我可以提供一个基于一个 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 是单线程构造的,因此此类任务的执行时间不会早于前一个任务完成,即。 e.响应已完全发送:

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

关于java - 服务请求后停止 HttpServer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36127945/

相关文章:

php - 对外部站点的 file_get_contents 请求

java - HTTP 测试服务器 : print all client requests to stdout

php - 应用程序在同一服务器上使用服务的最佳协议(protocol)?

c# - ServiceStack 心跳更新 session

node.js - http 服务器 : how to set the root directory of my server?

c# - ServiceStack服务OnUnsubscribe\OnSubscribe\OnConnect用户显示名称错误

java - keytool 如何将 keyUsage 与 -ext 一起使用

java - 如何将数据保存在多个 sql 行的一个 thymeleaf 页面中

java - 如何格式化 double 型变量

java - 一个 Java 泛型函数来合并 3 种类型的循环