我正在尝试创建非常简单的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
?
有人有任何工作彗星的例子吗?
P.S:我确实根据Tomcat配置切换到了Nio。
答案 0 :(得分:1)
init(ServletConfig)
的文档:
public void init(ServletConfig config) throws ServletException
被召唤 通过servlet容器向servlet指示servlet是什么 投入使用。请参阅Servlet #init。此实现存储ServletConfig对象 它从servlet容器接收供以后使用。什么时候覆盖 这种形式的方法,调用super.init(config)。
init()的文档:
public void init() throws ServletException
一种方便的方法 可以被覆盖,这样就不需要调用super.init(config)。不要覆盖init(ServletConfig),只需覆盖此方法即可 它将由GenericServlet.init(ServletConfig配置)调用。 仍然可以通过检索ServletConfig对象 getServletConfig()。
覆盖init(ServletConfig)时,您的第一个电话必须是super.init(config);