【问题标题】:Jetty How to add a servlet to multiple ServletContextHandler or apply ContainerRequestFilter to ContextHandlerCollectionJetty 如何将一个 servlet 添加到多个 ServletContextHandler 或将 ContainerRequestFilter 应用于 ContextHandlerCollection
【发布时间】:2018-11-15 04:54:29
【问题描述】:

当配置了多个ServletContextHandler时,我需要拦截所有的请求。

我在ContextHandlerCollectionContainerRequestFilter 中有多个ServletContextHandler。 我需要将这个ContainerRequestFilter 添加到所有ServletContextHandler 我能找到添加ContainerRequestFilter 的唯一方法是通过ResourceConfig。所以我这样做了:

ResourceConfig resourceConfig = new ResourceConfig();
resourceConfig.register(MyContainerRequestFilter.class);
ServletHolder s = new ServletHolder(new ServletContainer(resourceConfig));
for (Handler context : contextHandlers) {
    ((ServletContextHandler)context).addServlet(s, "/*");
} 

导致:

java.lang.IllegalStateException: 多个 servlet 映射到路径:/*: org.eclipse.jetty.proxy.ProxyServlet$Transparent-56c0a61e

这样做的正确方法是什么?

我还研究了处理程序并尝试了以下操作,但它覆盖了 ContextHandlerCollection 中包含的所有其他 servlet,即,当我调用 /api(存在于 ContextHandlerCollection 中的 ServletContextHandler 之一中)时,我得到 404,因为context.setContextPath("/"); 下面,但无论如何都需要在基本路径上应用此请求过滤器。

HandlerWrapper wrapper = new HandlerWrapper();
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
ResourceConfig resourceConfig = new ResourceConfig();
resourceConfig.register(RequestInterceptor.class);
context.addServlet(new ServletHolder(new ServletContainer(resourceConfig)), "/*");
wrapper.setHandler(context)
HandlerCollection handlers = new HandlerCollection(true);
handlers.setHandlers(new Handler[]{wrapper,contexts});

我也尝试在上面的集合中添加过滤器:

HandlerWrapper wrapper = new HandlerWrapper();
FilterHolder filter = new FilterHolder(MyContainerRequestFilter.class);  // had to implment filter interface
wrapper.addFilterWithMapping(filter, "/*", EnumSet.allOf(DispatcherType.class)) ;
HandlerCollection handlers = new HandlerCollection(true);
handlers.setHandlers(new Handler[]{contexts,wrapper});

在这种情况下,请求确实到达了过滤器,但我得到了以下异常:

无法发送响应错误 500: java.lang.IllegalStateException: Committed 404 前已提交 null

【问题讨论】:

  • " 我需要将此 ContainerRequestFilter 添加到所有 ServletContextHandler" - 这是什么意思? ContainerRequestFilter 与 ServletContextHandler 无关。它只是一个 Jersey 组件,只能在 Jersey 注册。您看到的错误来自您的循环,您正在尝试使用相同的映射/* 注册多个 Jersey servlet。你到底想完成什么?人们经常展示他们正在尝试完成某事的HOW,却忘记告诉我们WHAT。有时这会导致XY problem
  • @PaulSamsotha 为歧义道歉。简单地说,当配置了多个 ServletContextHandler 时,我需要拦截所有请求。我采取的方法是使用ContainerRequestFilter
  • “拦截所有请求”有多重含义。你想要一个 webapp 中的行为吗? (完成 ServletContext 行为?)或行为服务器范围(并且您不关心 ServletContext)?
  • 您的ServletContextHandler 实例是否通过DeploymentManager 被发现和部署?还是手动添加到HandlerList(或旧的HandlerCollection)?
  • @JoakimErdfelt 他们被手动添加到HandlerCollection

标签: java jersey jetty embedded-jetty


【解决方案1】:

我不能用ContainerRequestFilter 做到这一点,但我必须使用javax.servlet.Filter

在我的情况下(Multiple ServletContextHandler)添加javax.servlet.Filter的正确方法是:

Handler[] contextHandlers = contexts.getHandlers();

for (Handler context : contextHandlers) {
        ((ServletContextHandler)context).addFilter(RequestInterceptor.class, "/*", 
EnumSet.allOf(DispatcherType.class));
}

【讨论】:

  • 这不是所有 ServletContextHandlers 的过滤器的 1 个实例,就像您提出的问题一样,这是每个 ServletContextHandler 的唯一 RequestInterceptor 实例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-23
  • 1970-01-01
  • 2017-01-03
  • 2021-04-23
  • 2017-09-16
  • 2012-11-15
  • 2021-04-05
相关资源
最近更新 更多