首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Tomcat:在同一个web应用程序中使用servlet和websocket (jsr356)

Tomcat:在同一个web应用程序中使用servlet和websocket (jsr356)
EN

Stack Overflow用户
提问于 2017-05-27 12:21:47
回答 1查看 2K关注 0票数 6

我使用tomcat中的Guice-servlets和websocket创建了一个示例webapp,现在一旦使用guice过滤器就停止工作。

基本信息:

在我的web.xml中,我使用GuiceBasedListener初始化了Guiceservlet

代码语言:javascript
复制
<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

代码语言:javascript
复制
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代码

代码语言:javascript
复制
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

代码语言:javascript
复制
@ServerEndpoint(value = "/websocket/chat2")
public class WebSocket{
....
    @OnOpen
    public void start(Session session) {        
        System.out.println("Staring:"+this);
   }
....
}

Observations:

  1. 现在,如果我运行这个应用程序并点击http://app:8080/test,它会返回SUCCESS
  2. 但是如果我尝试使用ws://app:8080/ websocket /chat2 2连接到websocket,它就失败了。
  3. 现在,如果我评论serve("/*").with(MyDispatcher.class);,基本上如果我们关闭guice路由,websocket就开始工作了
  4. 如果我关闭guice,但在web.xml中添加servlet映射,像下面的websocket一样仍然有效。 < servlet-mapping > < servlet-name > HelloWorld< / servlet-name > < url-pattern > /* < / url-pattern > < / servlet-mapping >

我错过了什么或者做错了什么?

编辑:

Observation-conti:

  1. 我所做的是定义了一个简单的过滤器,它只使用FILTER响应。

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { response.getOutputStream().print("FILTER"); }

并将我的web.xml改为

代码语言:javascript
复制
<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

  1. 我把web.xml改成了下面,guice和websocket现在工作得很好。所以我认为Guice并不尊重在GuiceFilter之后注册的GuiceFilter myFilter org.apache.tomcat.websocket.server.WsFilter myFilter /* guiceFilter com.google.inject.servlet.GuiceFilter guiceFilter /*

TOMCAT 8.0,窗口7,Java 1.7,Guice 4.0,Guice-servlet-4.0

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-05-31 20:03:06

在我看来,这也是一个Guice问题(正如评论中已经提到的)。在同一个应用程序中使用servlet和WebSockets不应该是一个问题,即使使用涵盖/*的servlet映射也是如此。

有关servlet和过滤器的相关内容:

因此,如果WsFilter是第一个,它将首先拦截请求,然后是检查是否是WebSocket升级请求

如果它确实是一个WebSocket连接,则过滤器将不会将它传递给链的其余部分。

如果它是另一种类型的请求(GET,POST.),它将传递它,然后Guice将完成它的任务。

(所以你在这里找到了第一个解决方案)

如果Guice过滤器是第一个,并且您使用serve("/*")...,那么它会破坏您的WS。

如果您注释掉了serve("/*")...,那么GuiceFilter是否是第一个并不重要,WsFilter甚至可能不存在:您可以到达您的WS (只确定GuiceFilter是可以的)。

所以Guice在servlet映射之上有自己的“拦截层”,我认为这就是破坏WebSockets的原因。我不知道Guice中是否有bug或任何需要修复的地方(我的意思是可能的,但不知道具体是什么),但是您可以指定Guice的异常(与web.xml中的servlet映射不同)。

代之以:

代码语言:javascript
复制
serve("/*").with(TestServlet.class);

在这方面:

代码语言:javascript
复制
serveRegex("/(?!websocket/).*").with(TestServlet.class);
// Regex that accepts /.* but excludes /websocket/.*

这样,您可以保留/*上的servlet映射,并在不需要的情况下删除WsFilter。(测试,为我工作)

这是第二种解决方案,它还允许为非WebSocket指定异常。

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

https://stackoverflow.com/questions/44216801

复制
相关文章

相似问题

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