【发布时间】:2017-10-28 05:54:53
【问题描述】:
我在 tomcat 中使用 Guice-servlets 和 websocket 创建了一个示例 webapp,现在一旦使用 guice 过滤器,websocket 就会停止工作
基本信息:
在我的 web.xml 中,我使用 GuiceBasedListener 初始化了 Guiceservlet
<web-app>
<listener>
<listener-class>test.GuiceBasedListener</listener-class>
</listener>
<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
GuieBasedListener 将所有请求 /* 绑定到 MyDispatcher 的代码
public class GuiceBasedListener extends GuiceServletContextListener {
protected Injector getInjector() {
return Guice.createInjector( new ServletModule() {
@Override
protected void configureServlets() {
bind(MyDispatcher.class).asEagerSingleton();
serve("/*").with(MyDispatcher.class);//////IMPORTANT LINE//
}
});}}
MyDispatcher 只用字符串响应的代码
public class MyDispatcher extends HttpServlet {
@Inject private Injector injector;
public MyDispatcher() {}
public void service(ServletRequest req, ServletResponse resp) throws IOException, ServletException {
resp.getOutputStream().print("SUCCESS:" + req);
}
}
我还有一个用于 Websocket 的 @ServerEndPoint
@ServerEndpoint(value = "/websocket/chat2")
public class WebSocket{
....
@OnOpen
public void start(Session session) {
System.out.println("Staring:"+this);
}
....
}
观察:
- 现在,如果我运行应用程序并点击http://app:8080/test,它会返回
SUCCESS - 但如果我尝试使用 ws://app:8080/websocket/chat2 连接到 websocket,它会失败
现在,如果我评论
serve("/*").with(MyDispatcher.class);,基本上如果我们关闭 guice 路由,websocket 就会开始工作-
如果我关闭 guice-servlet 但在 web.xml 中添加一个 servlet 映射,如下 websocket 仍然有效
< servlet-mapping >< servlet-name > HelloWorld< / servlet-name >< url-pattern > /* < / url-pattern >< / servlet-mapping >
我错过了什么或做错了什么?
编辑:
观察连续性:
- 我所做的是定义了一个简单的过滤器,它只响应
FILTER。
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
response.getOutputStream().print("FILTER"); }
并将我的 web.xml 更改为
<web-app>
<filter>
<filter-name>myFilter</filter-name>
<filter-class>test.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
现在按预期点击http://localhost:8080/app/x 返回FILTER。
但是尝试与 websocket 连接失败,因为请求显示了这样的内容。
我还注意到,当我更改字符串 MyFilter 时,返回响应更改的内容长度,这意味着请求在 tomcat 为 websocket 处理之前到达MyFilter。
-
我将 web.xml 更改为下面,guice 和 websocket 现在工作正常.. 所以我认为 Guice 不尊重在 GuiceFilter 之后注册的 WsFilter
<filter> <filter-name>myFilter</filter-name> <filter-class>org.apache.tomcat.websocket.server.WsFilter</filter-class> </filter> <filter-mapping> <filter-name>myFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter> <filter-name>guiceFilter</filter-name> <filter-class>com.google.inject.servlet.GuiceFilter</filter-class> </filter> <filter-mapping> <filter-name>guiceFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
TOMCAT 8.0、Window 7、Java 1.7、Guice 4.0、Guice-servlet-4.0
【问题讨论】:
-
“我怎样才能告诉 tomcat 在匹配过滤器 url 模式之前首先考虑 serverEndPoint url 来路由请求?” 坦率地说,Tomcat 已经这样做了。您只是误解了实际问题的原因。我建议重写问题以详细说明观察到的实际问题的症状,而不是询问如何解决错误假设的可能原因。我推测
GuiceFilter只是一个错误,需要一个简单的错误修复,但只要您不详细说明实际观察到的症状,就不清楚究竟是什么。 -
@BalusC 你是对的......我已经重写了这个问题
-
“但是如果我尝试使用 ws://app:8080/websocket/chat2 连接到 websocket,它会失败” 它到底是怎么失败的?究竟发生了什么,究竟发生了什么,究竟发生了什么?
-
@BalusC 添加了一个有趣的观察结果
-
@BalusC 我认为 web.xml 中的过滤器是在 tomcat 的 WsFilter 之前注册的。只是猜测?
标签: tomcat servlets websocket guice-servlet jsr356