Tomcat 未为 Atmosphere servlet 调用过滤器
Tomcat filter not being invoked for Atmosphere servlet
我使用 Atmosphere 1.0.15 来处理 Tomcat 下的推送通知,几年来它一直运行良好。最近我在我的 Tomcat 中添加了一个简单的过滤器作为测试,它(当前)只记录传入的 URL 并继续。问题是对于我的 Atmosphere 处理的任何 servlet 路径,过滤器似乎根本不会被 Tomcat 调用,但对于任何其他 servlet 路径调用过滤器都很好。
这是我的 web.xml:
的相关部分
<servlet>
<description>AtmosphereServlet</description>
<servlet-name>AtmosphereServlet</servlet-name>
<servlet-class>org.atmosphere.cpr.AtmosphereServlet</servlet-class>
<init-param>
<param-name>org.atmosphere.atmosphereDotXml</param-name>
<param-value>WEB-INF/config/atmosphere.xml</param-value>
</init-param>
<!-- Reduce memory usage by sharing ExecutorServices -->
<init-param>
<param-name>org.atmosphere.cpr.broadcaster.shareableThreadPool</param-name>
<param-value>true</param-value>
</init-param>
<!-- Automatically free Broadcaster objects when the last client on the Broadcaster's channel disconnects -->
<init-param>
<param-name>org.atmosphere.cpr.broadcasterLifeCyclePolicy</param-name>
<param-value>EMPTY_DESTROY</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>AtmosphereServlet</servlet-name>
<url-pattern>/atmosphere/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>
com.foobar.MyFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这是我的 atmosphere.xml:
<atmosphere-handlers>
<atmosphere-handler context-root="/atmosphere/client-notification"
class-name="com.foobar.MyClientNotificationAtmosphereHandler"
comet-support="org.atmosphere.container.Tomcat7CometSupport">
</atmosphere-handler>
</atmosphere-handlers>
奇怪的是:如果我在 /atmosphere 下点击 URL 除了 之外的任何一个,我的过滤器就会被调用。例如,这工作正常并且我的过滤器被调用:
...但是,对于此 URL(或 /atmosphere 下的任何其他 URL),我的过滤器不会针对以下任何一项调用:
https://myserver:444/atmosphere/client-notification
https://myserver:444/atmosphere
https://myserver:444/atmosphere/foobar
我的第一个想法是 url-pattern 已关闭,但它被设置为“/*”,我的过滤器被调用用于除 /atmosphere 下的任何其他 URLs。我还尝试明确设置 url-pattern:
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/atmosphere/client-notification</url-pattern>
</filter-mapping>
...但仍然没有骰子。我错过了什么吗? Atmosphere 是否有可能阻止 运行 过滤器?据我了解,过滤器总是在 servlet 之前被调用,因此过滤器可以 "wrap" 调用它。
非常感谢任何建议!
所以经过大量的挖掘我发现了问题:因为 AtmosphereServlet class 执行异步 I/O 它实现了 org.apache.catalina.comet.CometProcessor 接口,所以 Tomcat不会为它调用正常的过滤器链,因为它是一个异步 servlet。相反,我的过滤器必须实现 CometFilter 接口,它可以在长 运行 请求保持活动状态时处理每个 Comet 事件。
一旦我发现 CometProcessor 是罪魁祸首,我就在此处找到了类似的 SO post:How do I get the requests for a servlet implementing CometProcessor interface to pass through a filter
我使用 Atmosphere 1.0.15 来处理 Tomcat 下的推送通知,几年来它一直运行良好。最近我在我的 Tomcat 中添加了一个简单的过滤器作为测试,它(当前)只记录传入的 URL 并继续。问题是对于我的 Atmosphere 处理的任何 servlet 路径,过滤器似乎根本不会被 Tomcat 调用,但对于任何其他 servlet 路径调用过滤器都很好。
这是我的 web.xml:
的相关部分<servlet>
<description>AtmosphereServlet</description>
<servlet-name>AtmosphereServlet</servlet-name>
<servlet-class>org.atmosphere.cpr.AtmosphereServlet</servlet-class>
<init-param>
<param-name>org.atmosphere.atmosphereDotXml</param-name>
<param-value>WEB-INF/config/atmosphere.xml</param-value>
</init-param>
<!-- Reduce memory usage by sharing ExecutorServices -->
<init-param>
<param-name>org.atmosphere.cpr.broadcaster.shareableThreadPool</param-name>
<param-value>true</param-value>
</init-param>
<!-- Automatically free Broadcaster objects when the last client on the Broadcaster's channel disconnects -->
<init-param>
<param-name>org.atmosphere.cpr.broadcasterLifeCyclePolicy</param-name>
<param-value>EMPTY_DESTROY</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>AtmosphereServlet</servlet-name>
<url-pattern>/atmosphere/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>
com.foobar.MyFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这是我的 atmosphere.xml:
<atmosphere-handlers>
<atmosphere-handler context-root="/atmosphere/client-notification"
class-name="com.foobar.MyClientNotificationAtmosphereHandler"
comet-support="org.atmosphere.container.Tomcat7CometSupport">
</atmosphere-handler>
</atmosphere-handlers>
奇怪的是:如果我在 /atmosphere 下点击 URL 除了 之外的任何一个,我的过滤器就会被调用。例如,这工作正常并且我的过滤器被调用:
...但是,对于此 URL(或 /atmosphere 下的任何其他 URL),我的过滤器不会针对以下任何一项调用:
https://myserver:444/atmosphere/client-notification
https://myserver:444/atmosphere
https://myserver:444/atmosphere/foobar
我的第一个想法是 url-pattern 已关闭,但它被设置为“/*”,我的过滤器被调用用于除 /atmosphere 下的任何其他 URLs。我还尝试明确设置 url-pattern:
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/atmosphere/client-notification</url-pattern>
</filter-mapping>
...但仍然没有骰子。我错过了什么吗? Atmosphere 是否有可能阻止 运行 过滤器?据我了解,过滤器总是在 servlet 之前被调用,因此过滤器可以 "wrap" 调用它。
非常感谢任何建议!
所以经过大量的挖掘我发现了问题:因为 AtmosphereServlet class 执行异步 I/O 它实现了 org.apache.catalina.comet.CometProcessor 接口,所以 Tomcat不会为它调用正常的过滤器链,因为它是一个异步 servlet。相反,我的过滤器必须实现 CometFilter 接口,它可以在长 运行 请求保持活动状态时处理每个 Comet 事件。
一旦我发现 CometProcessor 是罪魁祸首,我就在此处找到了类似的 SO post:How do I get the requests for a servlet implementing CometProcessor interface to pass through a filter