java - Apache Tomcat 简单 Comet Servlet

标签 java jakarta-ee tomcat servlets comet

我正在尝试创建非常简单的 Comet Servlet,它将向订阅者推送 Hello World 消息:

@WebServlet("/ChatServlet")
public class ChatServlet extends HttpServlet implements CometProcessor {
    private static final long serialVersionUID = 1L;

    private MessageSender messageSender = null;
    private static final Integer TIMEOUT = 60 * 1000;    

    public void init(ServletConfig config) throws ServletException {
          messageSender = new MessageSender();
            Thread messageSenderThread =
                    new Thread(messageSender);
            messageSenderThread.setDaemon(true);
            messageSenderThread.start();
        }

    public void destroy() {
     //   messageSender.stop();
        messageSender = null;
        }

    @Override
    public void event(CometEvent event) throws IOException, ServletException {
        HttpServletRequest request = event.getHttpServletRequest();
        HttpServletResponse response = event.getHttpServletResponse();
        if (event.getEventType() == CometEvent.EventType.BEGIN) {
            request.setAttribute("org.apache.tomcat.comet.timeout", TIMEOUT);
            System.out.println("Begin for session: " + request.getSession(true).getId());
            messageSender.setConnection(response);
        }
        else if (event.getEventType() == CometEvent.EventType.ERROR) {
            System.out.println("Error for session: " + request.getSession(true).getId());
            event.close();
        } else if (event.getEventType() == CometEvent.EventType.END) {
            System.out.println("End for session: " + request.getSession(true).getId());
            event.close();
        } else if (event.getEventType() == CometEvent.EventType.READ) {
            throw new UnsupportedOperationException("This servlet does not accept data");
    }
    }
}

然后我的 Runnable 看起来像这样:

public class MessageSender implements Runnable {

       protected boolean running = true;
        protected final List<String> messages = new ArrayList<String>();
        private ServletResponse connection;

        public synchronized void setConnection(ServletResponse connection){
            this.connection = connection;
            notify();
        }

    @Override
    public void run() {
         while (running) {
             if (messages.size() == 0) {
                    try {
                        synchronized (messages) {
                            messages.wait();
                        }
                    } catch (InterruptedException e) {
                        // Ignore
                    } 
         }
         String[] pendingMessages = null;
          synchronized (messages) {
              pendingMessages = messages.toArray(new String[0]);
              messages.clear();
          }
          try {
              if (connection == null){
                  try{
                      synchronized(this){
                          wait();
                      }
                  } catch (InterruptedException e){
                      // Ignore
                  }
              }
              PrintWriter writer = connection.getWriter();

                  writer.println("hello World");
                  System.out.println("Writing Hello World");                  
              writer.flush();
              writer.close();
              connection = null;
              System.out.println("Closing connection");
          } catch (IOException e) {
              System.out.println("IOExeption sending message"+e.getMessage());
          }
         }
    }
}

现在我的 Dojo cometd 代码如下所示:

  <script src="dojo/dojo.js"></script>    
    <script type="text/javascript">
    dojo.require("dojox.cometd");

    dojo.addOnLoad(function(){
        dojox.cometd.init("ChatServlet");
        dojox.cometd.subscribe("ChatServlet", window, "alertMessage");
    });

    function alertMessage(message) {
        alert("Message: " + message);
    }

    </script>

现在,当我加载客户端时,出现以下错误:

Begin for session: C898A372F1B1199C04CA308F715ABC36Nov 6, 2011 2:00:48 PM org.apache.catalina.core.StandardWrapperValve event
SEVERE: Servlet.service() for servlet [com.vanilla.servlet.ChatServlet] in context with path [/Servlet3Comet] threw exception
java.lang.UnsupportedOperationException: This servlet does not accept data
    at com.vanilla.servlet.ChatServlet.event(ChatServlet.java:75)

Error for session: C898A372F1B1199C04CA308F715ABC36
End for session: C898A372F1B1199C04CA308F715ABC36

我做错了什么? 为什么 cometD 订阅会调用 CometEvent.EventType.READ? 有人有任何有效的 cometd 示例吗?

P.S:我确实是按照Tomcat的配置切换到了Nio。

最佳答案

init(ServletConfig) 的文档:

public void init(ServletConfig config) throws ServletException Called by the servlet container to indicate to a servlet that the servlet is being placed into service.

See Servlet#init. This implementation stores the ServletConfig object it receives from the servlet container for later use. When overriding this form of the method, call super.init(config).

以及 init() 的文档:

public void init() throws ServletException A convenience method which can be overridden so that there's no need to call super.init(config).

Instead of overriding init(ServletConfig), simply override this method and it will be called by GenericServlet.init(ServletConfig config). The ServletConfig object can still be retrieved via getServletConfig().

重写 init(ServletConfig) 时,您的第一个调用必须是 super.init(config);

关于java - Apache Tomcat 简单 Comet Servlet,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8028106/

相关文章:

java - Apache POI : Writing into excel with Java: opening Workbook, java.io.IOException : Cannot write data, 文档似乎已关闭

java - 使用模式匹配从文件中排序,Java

java - 不同参数化类型参数的重载方法

java - 消息驱动 Bean-何时使用

java - 从部署到已运行的 Tomcat 8 实例的 Spring Boot WAR 文件中获取 Tomcat 运行的端口

java - Android 和 Lambda

java - Apache Ant 有什么方法可以让构建忽略错误

java - 限制用户每秒发出有限的请求

java - Tomcat 在哪里附加/到目录路径?

java - 连接池 : is it appropriate