您的位置:首页 > 其它

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

2015-02-02 00:31 288 查看
本例参考: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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: