代码之家  ›  专栏  ›  技术社区  ›  Yuval Herziger

Javax WebSockets不能与programmattic Tomcat 7实例化一起使用

  •  1
  • Yuval Herziger  · 技术社区  · 7 年前

    以下是我想做的:

    • 以编程方式设置Tomcat 7服务器 作品 使用一个简单的servlet。我仅从代码中定义Tomcat的端点,文件系统上没有设置或路由器(这是一个约束)。
    • 所述Tomcat服务器是否包含使用Javax Websockets API(1.1)的websocket服务器端点 不起作用

    我的应用程序/服务器入口点:

    package com.myapp;
    
    import java.io.File;
    import org.apache.catalina.Context;
    import org.apache.catalina.LifecycleException;
    import org.apache.catalina.deploy.FilterDef;
    import org.apache.catalina.deploy.FilterMap;
    import org.apache.catalina.startup.Tomcat;
    
    public class App 
    {
        public static void main(String[] args) throws LifecycleException
        {
            int port = 8080;
    
            Tomcat webServer = new Tomcat();
    
            webServer.setPort(port);
            webServer.setHostname("localhost");
            String appBase = ".";
            webServer.getHost().setAppBase(appBase);
            File docBase = new File(System.getProperty("java.io.tmpdir"));
            Context context = webServer.addContext("", docBase.getAbsolutePath());
    
            // both MyServlet and MyFilter exist and work.
            Class servletClass = MyServlet.class;
    
            Tomcat.addServlet(context, servletClass.getSimpleName(), servletClass.getName());
            context.addServletMapping("/my-servlet/*", servletClass.getSimpleName());
    
            Class filterClass = MyFilter.class;
            FilterDef myFilterDef = new FilterDef();
            myFilterDef.setFilterClass(filterClass.getName());
            myFilterDef.setFilterName(filterClass.getSimpleName());
            context.addFilterDef(myFilterDef);
    
            FilterMap myFilterMap = new FilterMap();
            myFilterMap.setFilterName(filterClass.getSimpleName());
            myFilterMap.addURLPattern("/my-servlet/*");
            context.addFilterMap(myFilterMap);
    
            webServer.start();
            webServer.getServer().await();
        }
    }
    

    我的websocket服务器终结点类:

    package com.myapp;
    
    import java.nio.ByteBuffer;
    import javax.websocket.OnClose;
    import javax.websocket.OnError;
    import javax.websocket.OnMessage;
    import javax.websocket.OnOpen;
    import javax.websocket.PongMessage;
    import javax.websocket.Session;
    import javax.websocket.server.ServerEndpoint;
    
    @ServerEndpoint("/web-socket/")
    public class WebSocket
    {
    
        @OnOpen
        public void onOpen()
        {
            System.out.println("Open Connection ...");
        }
    
         @OnMessage
        public static  void onTextMessage(Session session, String msg) {
            System.out.println("On Message for Web Socket");
        }   
        @OnMessage
        public void onBinaryMessage(Session session, ByteBuffer msg){
            System.out.println("On Message for Web Socket");
        }   
        @OnMessage
        public void onPongMessage(Session session, PongMessage pMsg) {
            System.out.println("On Message for Web Socket");
        }
        @OnClose
        public void onClose(Session session) {
            System.out.println("Connection Close for Web Socket");
        }
    
        @OnError
        public void onError(Throwable e)
        {
            e.printStackTrace();
        }
    }
    

    我使用的是Maven,我将WebSocket API包含在 <scope>provided</scope> ,正如我在其他问题中看到的,这是其他问题的根源。

    当我运行服务器时,我可以点击 my-servlet endpoint成功(当然是作为网页),但当我尝试创建WS对象时,只需在浏览器的开发控制台中使用 var webSocket = new WebSocket("ws://localhost:8080/web-socket") ,它说它不能到达终点:

    WebSocket connection to 'ws://localhost:8080/web-socket' failed: Error during WebSocket handshake: Unexpected response code: 404
    

    我的问题: 我错过了什么? 错误消息(来自Chrome)表明端点未注册(因此是404)。如何注册websocket ServerEndpoint?谢谢

    编辑:

    下面是我的实现 MyServlet 类别:

    package com.myapp;
    
    import java.io.IOException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class MyServlet extends HttpServlet
    {
    
        @Override
        protected void doGet(
                HttpServletRequest req,
                HttpServletResponse resp) throws IOException
        {
    
            resp.setStatus(HttpServletResponse.SC_OK);
            resp.getWriter().write("Works...");
            resp.getWriter().flush();
            resp.getWriter().close();
        }
    
    }
    

    下面是我对 MyFilter :

    package com.myapp;
    
    import java.io.IOException;
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletResponse;
    
    public class MyFilter implements Filter
    {
    
        @Override
        public void init(FilterConfig filterConfig)
        {
            // ...
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
        {
    
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            httpResponse.addHeader("myHeader", "myHeaderValue");
            chain.doFilter(request, httpResponse);
        }
    
        @Override
        public void destroy()
        {
            // ...
        }
    }
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   misterti    7 年前

    尝试手动添加web套接字终结点:

    
        String serverContainerClass = ServerContainer.class.getName();
        //should be "javax.websocket.server.ServerContainer", if not, some external package could have hogged the implementation
        final ServerContainer serverContainer = (ServerContainer) context.getServletContext().getAttribute(serverContainerClass);
        try 
        {
            serverContainer.addEndpoint(WebSocket.class);
        } 
        catch (DeploymentException e)
        {
            TraceWriter.Error(this, "Failed to initialize websocket", e);
        }
    
    

    您应该在将servlet添加到上下文后放置此代码