原理:
可以看:http://yiminghe.javaeye.com/blog/294781
AJAX 的出現使得 JavaScript 可以調用 XMLHttpRequest 對象發出 HTTP 請求,JavaScript 響應處理函數根據服務器返回的信息對 HTML 頁面的顯示進行更新。使用 AJAX 實現“服務器推”與傳統的 AJAX 應用不同之處在於:
- 服務器端會阻塞請求直到有數據傳遞或超時才返回。
- 客戶端 JavaScript 響應處理函數會在處理完服務器返回的信息后,再次發出請求,重新建立連接。
- 當客戶端處理接收的數據、重新建立連接時,服務器端可能有新的數據到達;這些信息會被服務器端保存直到客戶端重新建立連接,客戶端會一次把當前服務器端所有的信息取回。

聊天頁面的代碼:
定義mm.js,定義發送消息,定義接收消息的JS函數
- Ext.onReady(function () {
- getMsg();
- });
- function getMsg() {
- Ext.Ajax.request({url:"getMsg", callback:function (options, success, response) {
- if (success) {
- Ext.DomHelper.append(Ext.get("main"), response.responseText, true);
- }
- getMsg();
- }});
- }
- function putMsg() {
- Ext.Ajax.request({url:"putMsg", params:{message:document.getElementByIdx_x_x("message").value}});
- }
下面是獲得message的servlet
- package hyjc.listener;
- import java.io.IOException;
- import java.io.PrintWriter;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class GetMsg extends HttpServlet {
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- response.setContentType("text/html");
- PrintWriter out = response.getWriter();
- MessageList m = MessageList.getInstance();
- boolean end = false;
- while (!end) {
- System.out.println("before get");
- String msg = m.get();
- System.out.println("after get " + msg);
- out.write(msg + "
"); - if (m.isEmpty()) {
- end = true;
- }
- }
- out.close();
- }
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doGet(request, response);
- }
- }
下面是添加消息的servlet
- package hyjc.listener;
- import java.io.IOException;
- import java.io.PrintWriter;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class PutMsg extends HttpServlet {
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- response.setContentType("text/html");
- System.out.println("put message");
- PrintWriter out = response.getWriter();
- out.flush();
- String msg = request.getParameter("message");
- if (null != msg) {
- MessageList.getInstance().add(msg);
- } else {
- System.out.println("添加消息:" + msg + "成果");
- }
- out.close();
- }
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doGet(request, response);
- }
- }
下面是存放消息的消息隊列,內部用阻塞隊列使用
- package hyjc.listener;
- import java.util.Iterator;
- import java.util.concurrent.LinkedBlockingQueue;
- public class MessageList {
- private static MessageList list = null;
- private static Object key = new Object();
- private MessageList() {
- this.add("hello");
- this.add("world");
- }
- public static MessageList getInstance() {
- synchronized (key) {
- if (list == null) {
- list = new MessageList();
- }
- return list;
- }
- }
- private LinkedBlockingQueue queue = new LinkedBlockingQueue();
- public boolean isEmpty() {
- return queue.isEmpty();
- }
- public int size() {
- return queue.size();
- }
- public String get() {
- try {
- return queue.take();
- } catch (InterruptedException e) {
- e.printStackTrace();
- return null;
- }
- }
- public void clear() {
- queue.clear();
- }
- public void add(String msg) {
- try {
- queue.put(msg);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- public Iterator iterator() {
- return queue.iterator();
- }
- }
下面是演示效果,輸入message,點擊submit,就會添加到MessageList中,然后會在GetMsg中繼續執行,實現長連接


