Java tutorial
/** * Copyright (c)2010-2011 Enterprise Website Content Management System(EWCMS), All rights reserved. * EWCMS PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * http://www.ewcms.com */ package com.ewcms.web.pubsub; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Constructor; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.catalina.CometEvent; import org.apache.catalina.CometProcessor; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Servlet?Tomcat Comet??Tomcat 6.0?<br/> * <a href="http://tomcat.apache.org/tomcat-6.0-doc/aio.html">tomcat comet</a> * * @author wangwei */ public class PubsubServlet extends HttpServlet implements CometProcessor { private static final long serialVersionUID = 6492410972635853800L; private static final Logger logger = LoggerFactory.getLogger(PubsubServlet.class); private static final String INITIALDELAY_PARAM_NAME = "initialDelay"; private static final String DELAY_PARAM_NAME = "delay"; private static final String PUBSUB_CONTEXT = "pubsub"; private final Map<String, String> pathSender = new HashMap<String, String>(); private final Map<String, PubsubSenderable> senders = Collections .synchronizedMap(new HashMap<String, PubsubSenderable>()); private long initialDelay = 5; private long delay = 15; private void initInitialDelay() { String value = this.getInitParameter(INITIALDELAY_PARAM_NAME); if (StringUtils.isNumeric(value)) { initialDelay = Long.valueOf(value); } } private void initDelay() { String value = this.getInitParameter(DELAY_PARAM_NAME); if (StringUtils.isNumeric(value)) { delay = Long.valueOf(value); } } private void initPathMapSender() { Enumeration<?> names = this.getInitParameterNames(); for (; names.hasMoreElements();) { String path = (String) names.nextElement(); if (path.equals(INITIALDELAY_PARAM_NAME) || path.equals(DELAY_PARAM_NAME)) { continue; } String className = this.getInitParameter(path); String pubSubPath = StringUtils.substringAfter(path, PUBSUB_CONTEXT); pathSender.put(pubSubPath, className); } } @Override public void init() throws ServletException { initInitialDelay(); initDelay(); initPathMapSender(); } @Override public void destroy() { } /** * Comet event? * * ???<a href = "http://tomcat.apache.org/tomcat-6.0-doc/aio.html#Example_code">ChatServlet</a> * * @param event * The Comet event that will be processed * @throws IOException * @throws ServletException */ public void event(CometEvent event) throws IOException, ServletException { HttpServletRequest request = event.getHttpServletRequest(); HttpServletResponse response = event.getHttpServletResponse(); if (event.getEventType() == CometEvent.EventType.BEGIN) { logger.debug("Begin for session:{} ", request.getSession(true).getId()); String fullContentType = "text/html;charset=UTF-8"; response.setContentType(fullContentType); addConnection(request.getPathInfo(), response); } else if (event.getEventType() == CometEvent.EventType.ERROR) { logger.debug("Error for session: {}", request.getSession(true).getId()); removeConnection(response); event.close(); } else if (event.getEventType() == CometEvent.EventType.END) { logger.debug("End for session:{} ", request.getSession(true).getId()); removeConnection(response); event.close(); } else if (event.getEventType() == CometEvent.EventType.READ) { InputStream is = request.getInputStream(); byte[] buf = new byte[512]; do { int n = is.read(buf); // can throw an IOException if (n > 0) { logger.debug("Read {} bytes:{} for session:{}", new Object[] { n, new String(buf, 0, n), request.getSession(true).getId() }); } else if (n < 0) { return; } } while (is.available() > 0); } } private PubsubSenderable createPubsubSender(String path) { String name = null; if (StringUtils.indexOf(path, '/') == -1) { name = pathSender.get(path); } else { String root = StringUtils.substringBeforeLast(path, "/"); name = pathSender.get(root); if (name == null) { String middle = StringUtils.substringAfter(root, "/"); name = pathSender.get(middle); } } if (StringUtils.isNotBlank(name)) { try { Class<?> clazz = Class.forName(name); Class<?>[] argsClass = new Class<?>[] { String.class, ServletContext.class }; Constructor<?> cons = clazz.getConstructor(argsClass); return (PubsubSenderable) cons.newInstance(new Object[] { path, this.getServletContext() }); } catch (Exception e) { logger.error("PubsubSender create error:{}", e.toString()); } } return new NoneSender(); } private void addConnection(String path, HttpServletResponse connection) { synchronized (senders) { PubsubSenderable sender = senders.get(path); if (sender == null) { sender = createPubsubSender(path); sender.setDelay(delay); sender.setInitialDelay(initialDelay); sender.start(); senders.put(path, sender); } sender.addClient(connection); } } private void removeConnection(HttpServletResponse connection) { synchronized (senders) { for (PubsubSenderable sender : senders.values()) { sender.removeClient(connection); } } } }