首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >嵌入式Jetty:注册一个ServletContextListener的ServletRequestListener

嵌入式Jetty:注册一个ServletContextListener的ServletRequestListener
EN

Stack Overflow用户
提问于 2018-06-27 22:26:33
回答 1查看 4K关注 0票数 2

我使用的是嵌入式Jettyv9.4.x,有以下问题:

我的服务器注册了一个ServletContextListener

代码语言:javascript
运行
复制
    final WebAppContext context = new WebAppContext();

    // add listener
    context.addLifeCycleListener(new AbstractLifeCycle.AbstractLifeCycleListener() {
        @Override
        public void lifeCycleStarting(LifeCycle event) {

            ContextHandler.Context ctx = context.getServletContext();
            ctx.setExtendedListenerTypes(true);
            ctx.addListener("LISTENER_CLASS_NAME");
        }
    });

我的听众被叫到Servet。但是,我的上下文侦听器在下面注册了一个ServletRequestListener

代码语言:javascript
运行
复制
servletContext.addListener(foo.MyServletRequestListener.class);

除了以下例外,这是失败的:

代码语言:javascript
运行
复制
java.lang.UnsupportedOperationException
    at org.eclipse.jetty.servlet.ServletContextHandler$Context.addListener(ServletContextHandler.java:1506)

而且,当我查看时,上下文似乎没有启用(至少,这个标志使异常被抛出)。

当我使用web.xml运行相同的应用程序时,一切都可以工作。

如何让contextListener注册一个ServletRequestListener

编辑

在Jetty代码中有明确的注释:

代码语言:javascript
运行
复制
//toggle state of the dynamic API so that the listener cannot use it

这仅在编程添加的监听器上启用--使用的是API而不是web-xml

我怎样才能让这件事成功?

EN

回答 1

Stack Overflow用户

发布于 2018-06-27 23:20:38

Jetty中有许多不同类型的侦听器,每个监听器都有各自特定的add/remove/get/set方法集。

您的AbstractLifeCycleListener是一个Jetty侦听器,专门应用于Jetty内部Jetty内部启动/启动/停止Jetty中的各种bean。

在您的问题中,这个侦听器的实现是不完整的,并且表明您对LifeCycleEvent缺乏理解(您不是在寻找要启动的特定bean ),您的实现将运行数百次。(启动每个bean一次)。

ServletContext.addListener()的使用有其周围的规则,并且这些规则指定只能在ServletContext初始化阶段使用它(不能在此之前,不能在之后)。在这个阶段之外使用ServletContext.addListener()应该会抛出一个IllegalStateException ( javadoc甚至这么说)

ServletContext.addListener()还拥有一组有限的servlet侦听器,允许与其一起使用,远远少于在Web中有效或可以在WEB-INF/web.xml中声明或使用@WebListener注释标记的侦听器类型的数量。

使用ServletContext.addListener()的唯一方法是在webapp本身内使用webapp代码,并在webapp自己的类加载器中使用。

使用ServletContext.addListener()的地方是..。

如您所见,所有这些位置都是从webapp本身定义的。

ServletContextHandler.addEventListener(EventListener)的存在是一个嵌入式的跳槽,它允许在ServletContextHandler的构造中添加侦听器,但在实际事件发生之前不会调用。

ServletContextHandler.addEventListener(EventListener)的使用相当于使用WEB-INF/web.xml来声明您感兴趣的侦听器。

示例:

代码语言:javascript
运行
复制
package jetty.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;


public class ServletContextListenerExample
{
    public static void main(String[] args) throws Exception
    {
        Server server = new Server(8080);

        ServletContextHandler context = new ServletContextHandler();
        context.setContextPath("/");

        MyContextListener contextListener = new MyContextListener();
        context.addEventListener(contextListener);

        // for context based static file serving and error handling
        context.addServlet(DefaultServlet.class, "/");

        HandlerList handlers = new HandlerList();
        handlers.addHandler(context);
        // for non-context error handling
        handlers.addHandler(new DefaultHandler());

        server.setHandler(handlers);
        server.start();
        server.join();
    }

    public static class MyContextListener implements ServletContextListener
    {
        @Override
        public void contextInitialized(ServletContextEvent sce)
        {
            System.err.printf("MyContextListener.contextInitialized(%s)%n", sce);
            sce.getServletContext().addListener(new MyRequestListener());
        }

        @Override
        public void contextDestroyed(ServletContextEvent sce)
        {
            System.err.printf("MyContextListener.contextDestroyed(%s)%n", sce);
        }
    }

    public static class MyRequestListener implements ServletRequestListener
    {
        @Override
        public void requestDestroyed(ServletRequestEvent sre)
        {
            System.err.printf("MyRequestListener.requestDestroyed(%s)%n", sre);
        }

        @Override
        public void requestInitialized(ServletRequestEvent sre)
        {
            System.err.printf("MyRequestListener.requestInitialized(%s)%n", sre);
        }
    }
}

这将注册MyContextListener,它实现了两个javax.servlet.ServletContextListener。当ServletContext初始化阶段启动时,将触发contextInitialized()事件。然后,contextInitalized()的实现使用传入的ServletContext通过ServletContext.addListener() API添加一个新的MyRequestListener (实现javax.servlet.ServletRequestListener)。

输出上述内容,并从浏览器中点击http://localhost:8080/ .

代码语言:javascript
运行
复制
2018-06-28 09:42:06.352:INFO::main: Logging initialized @340ms to org.eclipse.jetty.util.log.StdErrLog
2018-06-28 09:42:06.475:INFO:oejs.Server:main: jetty-9.4.11.v20180605; built: 2018-06-05T18:24:03.829Z; git: d5fc0523cfa96bfebfbda19606cad384d772f04c; jvm 9.0.4+11
MyContextListener.contextInitialized(javax.servlet.ServletContextEvent[source=ServletContext@o.e.j.s.ServletContextHandler@12e61fe6{/,null,STARTING}])
2018-06-28 09:42:06.532:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@12e61fe6{/,null,AVAILABLE}
2018-06-28 09:42:06.695:INFO:oejs.AbstractConnector:main: Started ServerConnector@4567f35d{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
2018-06-28 09:42:06.695:INFO:oejs.Server:main: Started @690ms
MyRequestListener.requestInitialized(javax.servlet.ServletRequestEvent[source=ServletContext@o.e.j.s.ServletContextHandler@12e61fe6{/,null,AVAILABLE}])
MyRequestListener.requestDestroyed(javax.servlet.ServletRequestEvent[source=ServletContext@o.e.j.s.ServletContextHandler@12e61fe6{/,null,AVAILABLE}])

注意:这里讨论的Jetty上还有很多侦听器API和监听器类型,它们存在于与您的问题无关的Jetty的其他特性/组件中。不要被它们挂断,跳过它们,忽略它们,你就会没事的。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51072271

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档