Servlet3.0 异步处理 页面推送 Comet 实例

本例参考:http://blog.csdn.net/chenxiang0207/article/details/14054681/

我按照上面博文的思路重新走了一遍

项目结构如下图



/**
 * AsyncServlet
 * 
 * 支持异步处理的Servlet
 * 页面中隐藏的iframe通过访问此Servlet来建立HTTP长连接
 * 从而后台能实时的推送javascript代码给页面调用
 *
 */
@WebServlet(urlPatterns = "/Async", asyncSupported = true)
public class AsyncServlet extends HttpServlet {

	private static final long serialVersionUID = 822178713133426493L;
	private final static int DEFAULT_TIME_OUT = 10 * 60 * 1000;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse res) {
		AsyncContext actx = req.startAsync();
		actx.setTimeout(DEFAULT_TIME_OUT);
		actx.addListener(new AsyncListener() {

			@Override
			public void onComplete(AsyncEvent arg0) throws IOException {
				// TODO Auto-generated method stub
				ClientComet.getInstance().removeAsyncContext(actx);
				System.out.println("AsyncListener-->onComplete");
			}

			@Override
			public void onError(AsyncEvent arg0) throws IOException {
				// TODO Auto-generated method stub
				ClientComet.getInstance().removeAsyncContext(actx);
				System.out.println("AsyncListener-->onError");
			}

			@Override
			public void onStartAsync(AsyncEvent arg0) throws IOException {
				// TODO Auto-generated method stub
				System.out.println("AsyncListener-->onStartAsync");
			}

			@Override
			public void onTimeout(AsyncEvent arg0) throws IOException {
				// TODO Auto-generated method stub
				ClientComet.getInstance().removeAsyncContext(actx);
				System.out.println("AsyncListener-->onTimeout");
			}

		});
		ClientComet.getInstance().addAsyncContext(actx);
	}
}

/**
 * ClientComet
 * 
 * 管理用户的AsyncContext(添加、删除)
 * 
 * 通过开启一个线程来不断地从mesgQueue获取javascript 并遍历用户的AsyncContext来吧javascript推送给每个用户
 *
 */
public class ClientComet {
	private static ClientComet instance;
	private ConcurrentLinkedQueue<AsyncContext> actxQueue;
	private LinkedBlockingQueue<Javascript> mesgQueue;

	private ClientComet() {
		actxQueue = new ConcurrentLinkedQueue<AsyncContext>();
		mesgQueue = new LinkedBlockingQueue<Javascript>();
		new ClientCometThread().start();
	}

	public static ClientComet getInstance() {
		if (instance == null) {
			instance = new ClientComet();
		}
		return instance;
	}

	public void addAsyncContext(AsyncContext actx) {
		actxQueue.add(actx);
	}

	public void removeAsyncContext(AsyncContext actx) {
		actxQueue.remove();
	}

	public void callClient(Javascript javascript) {
		mesgQueue.add(javascript);
	}

	protected class ClientCometThread extends Thread {

		@Override
		public void run() {
			while (true) {
				try {
					Javascript javascript = mesgQueue.take();
					for (AsyncContext actx : actxQueue) {
						PrintWriter writer = actx.getResponse().getWriter();
						writer.write(javascript.getScript());
						writer.flush();
						System.out
								.println("ClientCometThread-->sendJavaScript");
					}
				} catch (InterruptedException | IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}
		}
	}

}

/**
 * Javascript
 *
 * 提供将javascript的方法调用补全到一个script标签中的功能
 */
public class Javascript {
	private String script;

	public Javascript(String func) {
		script = "<script type='text/javascript'>" + "\n" + "window.parent."
				+ func + "\n" + "</script>" + "\n";
	}

	public String getScript() {
		return script;
	}
}

/**
 * TestServlet
 * 
 * 访问此Servlet能够给ClientComet的mesgQueue添加对象
 *
 */
@WebServlet(urlPatterns = "/Test")
public class TestServlet extends HttpServlet {

	private static final long serialVersionUID = -7817902387051107187L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse res) {
		int times = 5;
		while (--times >= 0) {
			try {
				Thread.sleep(5000);
				ClientComet.getInstance().callClient(
						new Javascript("append(" + "\'"
								+ new Date().toGMTString() + "\'" + ")"));
				System.out.println("TestServlet-->callClient");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

Comet.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
	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 Test</title>
<script type='text/javascript'>
	function append(str) {
		var textField = document.getElementById("textField");
		textField.innerHTML = textField.innerHTML + str + "<br/>";
	};
</script>
</head>
<body>
	<!-- textField——用来显示服务器推送的内容 -->
	<p id="textField"></p>
	<!-- cometFrame——隐藏的iframe,用来访问AsyncServlet,建立长连接(注意,这样做window.onload的函数将失效,或直到此连接断开才执行) -->
	<iframe id="cometFrame" style="display: none;" src="/CometTest/Async"></iframe>
</body>
</html>



开启Tomcat

开启一个页面A先访问http://localhost:8080/CometTest/Comet.jsp

再打开一个新的页面B访问http://localhost:8080/CometTest/Test

此时能够看到A的内容不断的增加


PS:若想让onload函数不失效可以把对iframe的src的赋值操作放在onload中,而一开始src为空


项目打包:http://download.csdn.net/detail/u010497228/8415545


没有更多推荐了,返回首页

私密
私密原因:
请选择设置私密原因
  • 广告
  • 抄袭
  • 版权
  • 政治
  • 色情
  • 无意义
  • 其他
其他原因:
120
出错啦
系统繁忙,请稍后再试