Apache Tomcat 简单 Comet Servlet

4
我正在尝试创建一个非常简单的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? 有人有可行的comet示例吗?
附注:我按照Tomcat配置切换到了Nio。

抱歉,如果这已经过时了,请看看我的评论是否有帮助。彗星的路径是 BEGIN -> READ -> READ -> READ -> ERROR/TIMEOUT,在这里阅读 http://tomcat.apache.org/tomcat-6.0-doc/aio.html。所以你有一个开始,如果有数据,就会调用READ。尝试实现EventType.READ并查看发生了什么,从这里获取一些灵感 http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/chat/ChatServlet.java?revision=1380715&view=markup - Jasonw
1个回答

1

init(ServletConfig)的文档:

public void init(ServletConfig config) throws ServletException 由Servlet容器调用,以向Servlet指示将Servlet放入服务中。

请参见Servlet#init。 此实现将从Servlet容器接收到的ServletConfig对象存储供以后使用。 在覆盖此方法的形式时,请调用super.init(config)。

和init()的文档:

public void init() throws ServletException 可以重写的便捷方法,因此无需调用super.init(config)。

不要覆盖init(ServletConfig),只需覆盖此方法,它将由GenericServlet.init(ServletConfig config)调用。 ServletConfig对象仍然可以通过getServletConfig()检索。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接