Bhu*_*van 6 tomcat servlets websocket guice-servlet jsr356
我在tomcat中使用Guice-servlets和websocket创建了一个示例webapp,现在一次使用guice过滤器websocket停止工作
在我的web.xml中,我使用了初始化Guiceservlet GuiceBasedListener
<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>
Run Code Online (Sandbox Code Playgroud)
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//
}
});}}
Run Code Online (Sandbox Code Playgroud)
MyDispatcher
只用String响应的代码
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);
}
}
Run Code Online (Sandbox Code Playgroud)
我还有一个@ServerEndPoint for Websocket
@ServerEndpoint(value = "/websocket/chat2")
public class WebSocket{
....
@OnOpen
public void start(Session session) {
System.out.println("Staring:"+this);
}
....
}
Run Code Online (Sandbox Code Playgroud)
观察:
SUCCESS
现在,如果我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>
Run Code Online (Sandbox Code Playgroud)
现在按预期命中http://localhost:8080/app/x
回报FILTER
.但尝试连接websocket失败,因为请求显示这样的事情.我还注意到,当我更改String MyFilter
返回响应中的内容长度更改时,这意味着MyFilter
在tomcat处理websocket之前已达到请求.
我将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>
Run Code Online (Sandbox Code Playgroud)TOMCAT 8.0,Window 7,Java 1.7,Guice 4.0,Guice-servlet-4.0
对我来说,这也看起来像是一个 Guice 问题(正如评论中已经提到的)。在同一应用程序中使用 servlet 和 WebSocket 应该不成问题,即使 servlet 映射涵盖/*
.
2 与 servlet 和过滤器相关的事情:
所以,如果 WsFilter 是第一个,它会先拦截该请求,然后检查是否是 WebSocket 升级请求。
如果确实是 WebSocket 连接,则过滤器不会将其传递到链的其余部分。
如果是另一种类型的请求(GET、POST...),它会将其传递,然后 Guice 将执行其操作。
(所以你在这里找到了第一个解决方案)
如果 Guice 过滤器是第一个,并且您使用serve("/*")...
,那么它会破坏您的 WS。
如果你注释掉serve("/*")...
,那么 Guice Filter 是否在先并不重要,WsFilter 甚至可以不存在:你的 WS 是可以到达的(单独建立 GuiceFilter 就可以了)。
因此,Guice 在 servlet 映射之上有自己的“拦截层”,我认为这就是破坏 WebSocket 的原因。我不知道 Guice 中是否有错误或任何需要修复的内容(我的意思是可能,但不知道具体是什么),但您可以指定 Guice 的例外情况(与 中的 servlet 映射不同web.xml
)。
替换这个:
serve("/*").with(TestServlet.class);
Run Code Online (Sandbox Code Playgroud)
有了这个:
serveRegex("/(?!websocket/).*").with(TestServlet.class);
// Regex that accepts /.* but excludes /websocket/.*
Run Code Online (Sandbox Code Playgroud)
这样,您就可以将 servlet 映射保留在 上/*
,并WsFilter
在不需要时将其删除。(经过测试,对我有用)
这是第二种解决方案,它的优点是它还允许为非 WebSocket 内容指定异常。
归档时间: |
|
查看次数: |
1166 次 |
最近记录: |