3

我正在使用 Grizzly 为 Jersey 应用程序提供服务,同时使用 Logback 来满足我的日志记录需求。请注意这里不Servlet涉及 s,我使用如下代码“手动”启动所有内容:

final URI uri = /* this is a configuration option */        
this.server = new HttpServer();
final NetworkListener nl = new NetworkListener(
    "grizzly", uri.getHost(), uri.getPort());
server.addListener(nl);

final GuiceComponentProviderFactory gcpf =
    new GuiceComponentProviderFactory(rc, inj);
final HttpHandler processor = ContainerFactory.createContainer(
    HttpHandler.class, rc, gcpf);
this.server.getServerConfiguration().addHttpHandler(
    processor, uri.getPath());
server.start();

现在我想使用 Logback 的MDC功能使客户端的套接字地址在日志记录中可见。为此,我需要一些地方将侦听器连接到 HTTP 处理,该处理会收到有关传入请求(我可以将地址放入 MDC)和请求完成时的通知(以便我可以清理 MDC)。我采用的一种方法是将Container*Filter实例与 Jersey 连接起来,如下所示:

class MdcFilter implements
        ContainerRequestFilter, ContainerResponseFilter {

    @Override
    public ContainerRequest filter(ContainerRequest request) {
        MDC.put("http-client", "foo" /* no way to get the address here */);
        return request;
    }

    @Override
    public ContainerResponse filter(
            ContainerRequest request,
            ContainerResponse response) {

        MDC.remove("http-client");
        return response;
    }

}

不幸的是,泽西岛ContainerRequest没有提供有关已连接客户端的信息(这确实令人惊讶)。

我怀疑灰熊本身应该存在类似的界面,但我无法将其挖掘出来。

4

2 回答 2

4

对于 Grizzly,相关的 API 被调用HttpServerProbe。使用它,它归结为这样的事情:

final HttpServer server = new org.glassfish.grizzly.http.server.HttpServer();
server.addListener(new NetworkListener("grizzly", "localhost", 8080));
server.getServerConfiguration().addHttpHandler(
    new StaticHttpHandler("/var/www/"), "/");

server.getServerConfiguration().getMonitoringConfig().getWebServerConfig()
  .addProbes(new HttpServerProbe.Adapter() {

    @Override
    public void onRequestReceiveEvent(
        HttpServerFilter filter,
        Connection connection,
        Request request) {

      System.out.println(request.getRemoteAddr());
      MDC.put("http-client", request.getRemoteAddr());
    }

    @Override
    public void onRequestCompleteEvent(
        HttpServerFilter filter,
        Connection connection,
        Response response) {

      MDC.remove("http-client");
    }
}

server.start();

请注意,还有更多可能相关的事件,例如挂起、恢复和取消。这些也应该被处理,尤其是在使用长轮询(又名 Comet,又名whatnot)的情况下。但基本上这是挂钩的地方。

于 2013-06-24T15:56:18.913 回答
-1

在您的MdcFilter中,尝试将 注入HttpServletRequest您的类并像通常调用的那样使用它getRemoteAddr()或任何其他此类函数,例如:

class MdcFilter implements
    ContainerRequestFilter, ContainerResponseFilter {

    @Context
    protected HttpServletRequest r;

    @Override
    public ContainerRequest filter(ContainerRequest request) {
        MDC.put("http-client", "foo" r.getRemoteAddr());
        return request;
    }

    @Override
    public ContainerResponse filter(ContainerRequest request, ContainerResponse response) {
        MDC.remove("http-client");
        return response;
    }
}

我使用类似的“手动启动”的方法对此进行了测试,在这种情况下它对我来说很有效。我想它也对你有用。

于 2013-06-22T11:49:23.023 回答