首先是一些(非常基本的)示例代码来说明我的问题:

final java.util.concurrent.atomic.AtomicLong previousId = new java.util.concurrent.atomic.AtomicLong();
final com.sun.net.httpserver.HttpServer server = com.sun.net.httpserver.HttpServer.create(new java.net.InetSocketAddress(8666), 0);
server.setExecutor(java.util.concurrent.Executors.newCachedThreadPool());
server.createContext("/", exchange -> {
  final long id = previousId.incrementAndGet();
  System.out.println(String.format("#%s: id attribute=%s", id, exchange.getAttribute("id")));
  exchange.setAttribute("id", id);
  while (true) {
    try {
      Thread.sleep(1_000);
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      return;
    }
    System.out.println(String.format("#%s: id attribute=%s", id, exchange.getAttribute("id")));
  }
});
server.start();


在运行此程序时(在Java SE 1.8.0_171上),如果我连续两次向http://localhost:8666请求,则会得到以下日志:

#1: id attribute=null
#1: id attribute=1
#1: id attribute=1
#2: id attribute=1
#1: id attribute=2
#2: id attribute=2
#1: id attribute=2
#2: id attribute=2


对于请求#1,属性最初是null,如预期的那样。对于请求2,该属性最初是1,这似乎意味着初始值是从其他请求继承的。如您所见,更糟糕的是,将请求2的值更改为2还将请求1的值更改为2。似乎属性在HttpExchange实例之间共享,这不是我期望的。

我缺少什么还是HttpExchange属性损坏了吗?

最佳答案

the source code看,很显然,HttpExchange属性由同一HttpContext上的所有实例共享。尽管在setAttribute上定义了getAttributeHttpExchange方法,但我发现它具有误导性。我认为Javadoc没有帮助:


筛选器模块可以将带有HttpExchange实例的任意对象存储为带外通信机制。


我有sent an email to the net-dev mailing listfiled a bug。收到一些消息后,我将立即更新此答案。

07-26 06:26