با مراجعه به یکی از لینکهای موجود در جواب مرتبط اقدام به تهیه یک سرولت برای ایجاد کامت کردم.
برای این منظور فایل server.xml در tomcat را به شیوه زیر تغییر دادم:
<Connector connectionTimeout="20000" port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" redirectPort="8443"/>
و یک سرولت به صورت زیر ایجاد کردم:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.mohi.comet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import javax.servlet.ServletException;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.comet.CometEvent;
import org.apache.catalina.comet.CometProcessor;
/**
*
* @author mohsen
*/
@WebServlet("/mn")
public class NotificationComet extends HttpServlet implements CometProcessor {
public static int ii = 1;
private MessageSender messageSender = null;
private static final Integer TIMEOUT = 60 * 1000;
@Override
public void destroy() {
// messageSender.stop();
messageSender = null;
}
@Override
public void init() throws ServletException {
messageSender = new MessageSender();
Thread messageSenderThread =
new Thread(messageSender, "MessageSender[" + getServletContext()
.getContextPath() + "]");
messageSenderThread.setDaemon(true);
messageSenderThread.start();
}
@Override
public void event(final 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);
log("Begin for session: " + request.getSession(true).getId());
messageSender.setConnection(response);
Weatherman weatherman = new Weatherman();
new Thread(weatherman).start();
} else if (event.getEventType() == CometEvent.EventType.ERROR) {
log("Error for session: " + request.getSession(true).getId());
event.close();
} else if (event.getEventType() == CometEvent.EventType.END) {
log("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");
}
}
private class MessageSender implements Runnable {
protected boolean running = true;
protected final ArrayList<String> messages = new ArrayList<String>();
private ServletResponse connection;
private synchronized void setConnection(ServletResponse connection) {
this.connection = connection;
notify();
}
public void send(String message) {
synchronized (messages) {
messages.add(message);
System.err.println("Message added #messages=" + messages.size());
messages.notify();
}
}
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();
for (int j = 0; j < pendingMessages.length; j++) {
final String forecast = pendingMessages[j] + "<br>";
writer.println(forecast);
System.err.println("Writing:" + forecast);
}
writer.flush();
writer.close();
connection = null;
System.err.println("Closing connection");
} catch (IOException e) {
System.err.println("IOExeption sending message");
e.printStackTrace();
}
}
}
}
private class Weatherman implements Runnable {
public void run() {
int i = 0;
while (i >= 0) {
try {
messageSender.send(i+"gooooolaaaaa"+ii++);
Thread.sleep(30000L);
} catch (Exception e) {
// just eat it, eat it
}
i++;
}
}
}
}
و در نهایت یک jsp هم به صورت زیر:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Comet Weather</title>
<SCRIPT TYPE="text/javascript">
function go() {
var url = "http://localhost:8080/test_servlet/mn"
var request = new XMLHttpRequest();
request.open("GET", url, true);
request.setRequestHeader("Content-Type", "application/x-javascript;");
request.onreadystatechange = function() {
if (request.readyState == 4) {
if (request.status == 200) {
if (request.responseText) {
document.getElementById("forecasts").innerHTML =
request.responseText;
}
}
go();
}
};
request.send(null);
}
</SCRIPT>
</head>
<body>
<h1>Rapid Fire Weather </h1>
<input type="button" onclick="go()" value="برو!"></input>
<div id="forecasts"></div>
</body>
</html>
اما مشکلم در اینجا است که پس از فشردن دکمه برو! متد event موجود servlet به صورت پشت سر هم و بدون وقفه فراخوانی می شود و بدون وقفه Thread های جدید ایجاد می شود. مشکل کارم از کجاست؟