Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<servlet-mapping>
<servlet-name>PushAction</servlet-name>
<url-pattern>/PushAction</url-pattern>
</servlet-mapping>
<servlet>
<description></description>
<display-name>PushAction</display-name>
<servlet-name>PushAction</servlet-name>
<servlet-class>org.nipc.PushAction</servlet-class>
<async-supported>true</async-supported>
</servlet>
<listener>
<listener-class>org.nipc.PushListener</listener-class>
</listener>
</web-app>
PushAction.java
package org.nipc;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Servlet implementation class PushAction
*/
//@WebServlet(urlPatterns = { "/PushAction" }, asyncSupported = true)
public class PushAction extends HttpServlet {
private static final long serialVersionUID = 1L;
// private static final Logger logger = LoggerFactory.getLogger(PushAction.class);
/**
* @see HttpServlet#HttpServlet()
*/
public PushAction() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.setHeader("Cache-Control", "private");
response.setHeader("Pragma", "no-cache");
response.setContentType("text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
final PrintWriter writer = response.getWriter();
// 创建Comet Iframe
writer.println("<!doctype html public \"-//w3c//dtd html 4.0 transitional//en\">");
writer.println("<script type=\"text/javascript\">var comet = window.parent.comet;</script>");
writer.flush();
// ((org.apache.catalina.connector.Request)request).setAsyncSupported(true);
final AsyncContext ac = request.startAsync();
ac.setTimeout(10 * 60 * 1000);// 10分钟时间;tomcat7下默认为10000毫秒
ac.addListener(new AsyncListener() {
public void onComplete(AsyncEvent event) throws IOException {
// logger.info("the event : " + event.toString() + " is complete now !");
PushListener.ASYNC_AJAX_QUEUE.remove(ac);
}
public void onTimeout(AsyncEvent event) throws IOException {
// logger.info("the event : " + event.toString() + " is timeout now !");
// 尝试向客户端发送超时方法调用,客户端会再次请求/blogpush,周而复始
// logger.info("try to notify the client the connection is timeout now ...");
String alertStr = "time out";
writer.println(alertStr);
writer.flush();
writer.close();
PushListener.ASYNC_AJAX_QUEUE.remove(ac);
}
public void onError(AsyncEvent event) throws IOException {
// logger.info("the event : " + event.toString() + " is error now !");
PushListener.ASYNC_AJAX_QUEUE.remove(ac);
}
public void onStartAsync(AsyncEvent event) throws IOException {
// logger.info("the event : " + event.toString() + " is Start Async now !");
}
});
PushListener.ASYNC_AJAX_QUEUE.add(ac);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
}
PushListener
package org.nipc;
import java.io.PrintWriter;
import java.util.Queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingDeque;
import javax.servlet.AsyncContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Application Lifecycle Listener implementation class PushListener
*
*/
//@WebListener
public class PushListener implements ServletContextListener {
// private static final Logger logger = LoggerFactory.getLogger(PushListener.class);
public static BlockingQueue<String> MSG_QUEUE = new LinkedBlockingDeque<String>();
public static final Queue<AsyncContext> ASYNC_AJAX_QUEUE = new ConcurrentLinkedQueue<AsyncContext>();
/**
* @see ServletContextListener#contextInitialized(ServletContextEvent)
*/
public void contextInitialized(ServletContextEvent arg0) {
// TODO Auto-generated method stub
// logger.info("context is initialized!");
// 启动一个线程处理线程队列
new Thread(runnable).start();
}
/**
* @see ServletContextListener#contextDestroyed(ServletContextEvent)
*/
public void contextDestroyed(ServletContextEvent arg0) {
// TODO Auto-generated method stub
// logger.info("context is destroyed!");
}
private Runnable runnable = new Runnable() {
public void run() {
boolean isDone = true;
while (isDone) {
MSG_QUEUE.add("Hello");
MSG_QUEUE.add("Hello");
MSG_QUEUE.add("Hello");
MSG_QUEUE.add("Hello");
if (!MSG_QUEUE.isEmpty()) {
try {
// logger.info("ASYNC_AJAX_QUEUE size : " + ASYNC_AJAX_QUEUE.size());
String msg = MSG_QUEUE.take();
if (ASYNC_AJAX_QUEUE.isEmpty()) {
continue;
}
// String targetJSON = getFormatContent(blog);
for (AsyncContext context : ASYNC_AJAX_QUEUE) {
if (context == null) {
// logger.info("the current ASYNC_AJAX_QUEUE is null now !");
continue;
}
// logger.info(context.toString());
PrintWriter out = context.getResponse().getWriter();
if (out == null) {
// logger.info("the current ASYNC_AJAX_QUEUE's PrintWriter is null !");
continue;
}
out.println(msg);
out.flush();
}
} catch (Exception e) {
e.printStackTrace();
isDone = false;
}
}
}
}
};
}