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; } } } } }; }