嵌入式Jetty:ServletContextListener,用于注册ServletRequestListener

嵌入式Jetty:ServletContextListener,用于注册ServletRequestListener,jetty,embedded-jetty,Jetty,Embedded Jetty,我使用的是嵌入式Jetty v9.4.x,存在以下问题: 我的服务器注册了一个ServletContextListener: final WebAppContext context = new WebAppContext(); // add listener context.addLifeCycleListener(new AbstractLifeCycle.AbstractLifeCycleListener() { @Override

我使用的是嵌入式Jetty v9.4.x,存在以下问题:

我的服务器注册了一个
ServletContextListener

    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 start上被调用。但是,我的上下文侦听器在以下内部注册了一个
ServletRequestListener

servletContext.addListener(foo.MyServletRequestListener.class);
此操作失败,但出现以下例外情况:

java.lang.UnsupportedOperationException
    at org.eclipse.jetty.servlet.ServletContextHandler$Context.addListener(ServletContextHandler.java:1506)
当我查看时,上下文似乎未启用(至少,该标志会引发异常)

当我用
web.xml
运行同一个应用程序时,一切都正常

如何让contextListener注册
ServletRequestListener

编辑 码头规范中有明确说明:

//toggle state of the dynamic API so that the listener cannot use it
这仅在通过编程添加的侦听器上启用-使用API而不是
WebXML


我怎样才能做到这一点呢?

Jetty中有许多不同类型的侦听器,每个侦听器都有自己特定的添加/删除/获取/设置方法集

您的
AbstractLifeCycleListener
是Jetty生命周期监听器,专门用于Jetty内部启动/启动/停止/停止Jetty中的各种bean

您在问题中对该侦听器的实现是不完整的,并且显示出您对
LifeCycleEvent
的理解不足(您没有寻找要启动的特定bean),您的实现将运行数百次。(每启动一个bean一次)

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

ServletContext.addListener()
也有一组允许与之一起使用的有限的servlet侦听器,远远少于Web应用程序有效的侦听器类型的数量,或者可以在
Web-INF/Web.xml
中声明,或者用
@WebListener
注释标记的侦听器类型的数量

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

要使用的位置是

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

ServletContextHandler.addEventListener(EventListener)
的存在是一个嵌入式jetty解决方案,它允许在构建
ServletContextHandler
时添加侦听器,但在实际事件发生之前不调用侦听器

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

例如:

包jetty.listener;
导入javax.servlet.ServletContextEvent;
导入javax.servlet.ServletContextListener;
导入javax.servlet.ServletRequestEvent;
导入javax.servlet.ServletRequestListener;
导入org.eclipse.jetty.server.server;
导入org.eclipse.jetty.server.handler.DefaultHandler;
导入org.eclipse.jetty.server.handler.HandlerList;
导入org.eclipse.jetty.servlet.DefaultServlet;
导入org.eclipse.jetty.servlet.ServletContextHandler;
公共类ServletContextListenerExample
{
公共静态void main(字符串[]args)引发异常
{
服务器=新服务器(8080);
ServletContextHandler上下文=新的ServletContextHandler();
context.setContextPath(“/”);
MyContextListener contextListener=新的MyContextListener();
addEventListener(contextListener);
//用于基于上下文的静态文件服务和错误处理
addServlet(DefaultServlet.class,“/”);
HandlerList handlers=new HandlerList();
addHandler(上下文);
//用于非上下文错误处理
addHandler(新的DefaultHandler());
setHandler(处理程序);
server.start();
join();
}
公共静态类MyContextListener实现ServletContextListener
{
@凌驾
public void contextInitialized(ServletContextEvent sce)
{
System.err.printf(“MyContextListener.contextInitialized(%s)%n”,sce);
sce.getServletContext().addListener(新的MyRequestListener());
}
@凌驾
公共无效上下文已销毁(ServletContextEvent sce)
{
System.err.printf(“MyContextListener.contextDestroyed(%s)%n”,sce);
}
}
公共静态类MyRequestListener实现ServletRequestListener
{
@凌驾
公共无效请求已销毁(ServletRequestEvent sre)
{
System.err.printf(“MyRequestListener.requestdestromed(%s)%n”,sre);
}
@凌驾
public void requestInitialized(ServletRequestEvent sre)
{
System.err.printf(“MyRequestListener.requestInitialized(%s)%n”,sre);
}
}
}
这将注册
MyContextListener
,它同时实现了
javax.servlet.ServletContextListener
。 当
ServletContext
初始化阶段开始时,将触发
contextInitialized()
事件。
contextinitialized()
的实现然后使用传入的
ServletContext
通过
ServletContext.addListener()
API添加一个新的
MyRequestListener
(它实现了
javax.servlet.ServletRequestListener

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

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和侦听器类型,这些API和侦听器类型用于其他功能