為滿足 EasyJF 開源團隊遠程協作需求,開發一套模擬傳統會議形式的網上會議室系統。核心功能包括:多會議室並發、權限控管、發言模式切換(排隊/自由)、歷史記錄持久化、遊客與論壇帳號整合、文字聊天為主並預留語音視訊擴充介面。
// 會議室實體
public class ChatRoom {
private String cid; // 主鍵
private String title; // 主題
private String intro; // 簡介
private String announce; // 公告
private String owner; // 創建人
private Integer maxUser; // 最大人數
private Integer intervals; // 刷新間隔
private String vrtype; // 訪問權限類型
private String vrvalue; // 訪問值
private Integer status; // 狀態
private Date inputTime; // 創建時間
// ... getter/setter
}
// 發言記錄
public class Chat {
private String cid;
private String sender; // 發言人
private String reciver; // 接收人
private String content; // 內容
private Date vdate; // 時間
private Integer types; // 類型
private Integer status;
}
// 參會用戶
public class ChatUser {
private String ip;
private String port;
private String userName;
private Date lastAccessTime; // 最後活躍時間
private Integer status; // 在線/離線/發言中...
}
// 排隊發言者
public class Talker {
private String userName;
private Date startTime;
private Date estimatedEndTime;
}
Map<String, ChatService>)Runnable,每個會議室獨立線程維護狀態(run() 每 5 秒輪詢)create()、close()、get()、talk()、exit()、Flash()(刷新持久化)setTimeout 5 秒)對比 Form 提交、自動刷新、ActiveXObject:AJAX 無感知刷新、用戶體驗最佳、XML 結構化資料便於 JavaScript 處理。
public class ChatAction extends AbstractCmdAction {
private ChatService chatRoom;
public Object doBefore(WebForm form, Module module) {
if (chatRoom == null)
chatRoom = ChatService.get((String)form.get("cid"));
return super.doBefore(form, module);
}
// 進入會議室
public Page doMain(WebForm form, Module module) {
if (chatRoom != null) {
ChatUser user = getChatUser();
if (!chatRoom.join(user)) form.addResult("msg", "權限不足");
form.addResult("chatRoom", chatRoom);
form.addResult("user", user);
} else {
form.addResult("msg", "會議未啟動或不存在");
}
return module.findPage("main");
}
// 發言處理
public Page doSend(WebForm form, Module module) {
if (chatRoom == null) return new Page("err", "/err.html");
Chat chat = (Chat) form.toPo(Chat.class);
chat.setCid(chatRoom.geneId());
chatRoom.talk(chat);
return doRecive(form, module); // 發言後立即拉取最新
}
// 拉取新訊息
public Page doRecive(WebForm form, Module module) {
String lastReadId = CommUtil.null2String(form.get("lastReadId"));
form.addResult("list", chatRoom.getNewestMsg(getChatUser(), lastReadId));
return module.findPage("msgList"); // 返回 XML 片段
}
// 狀態同步
public Page doLoadConfig(WebForm form, Module module) {
form.addResult("userList", chatRoom.getUsers());
form.addResult("talkerList", chatRoom.getTalkers());
return module.findPage("config");
}
}
// 跨瀏覽器 XMLHttpRequest 工廠
function newXMLHttpRequest() {
if (window.XMLHttpRequest) return new XMLHttpRequest();
try { return new ActiveXObject("Msxml2.XMLHTTP"); }
catch(e) { return new ActiveXObject("Microsoft.XMLHTTP"); }
}
// 統一 AJAX 執行器
function executeAJaxCommand(url, postData, handleMethod) {
var req = newXMLHttpRequest();
req.onreadystatechange = handleAJaxResult(req, handleMethod);
req.open("POST", url, true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.setRequestHeader("charset", "utf-8");
req.send(postData);
}
// 發言
function doSend() {
if (!check()) return false;
var url = "/chat.ejf?easyJWebCommand=send&cid=" + roomId + "&lastReadId=" + lastReadId;
var postData = "sender=" + myName + "&reciver=" + reciver + "&content=" + msg;
clearTimeout(reciveTime);
executeAJaxCommand(url, postData, "recive");
EditForm.content.value = "";
}
// 處理回調
function handleAJaxResult(req, method) {
return function() {
if (req.readyState == 4 && req.status == 200) {
var objXMLDoc = new ActiveXObject("Microsoft.XMLDOM");
objXMLDoc.loadXML(req.responseText);
eval("if(objXMLDoc.firstChild) " + method + "(objXMLDoc.firstChild.nextSibling);");
}
};
}
// 接收訊息回調
function recive(list) {
var id = "";
for (var oNode = list.firstChild; oNode; oNode = oNode.nextSibling) {
chatContent.innerHTML += showMsg(oNode);
id = oNode.getAttribute("cid");
}
if (id) lastReadId = id;
chatContent.scrollTop = chatContent.scrollHeight;
reciveTime = setTimeout("doRecive();", 5000);
}
線上演示:EasyJF 會議室體驗
AJAX 本質是 JavaScript、DHTML、CSS、XMLDOM、XMLHttpRequest 等成熟技術的組合。對資深工程師,重點在業務與系統級演算法設計;對新手,夯實客戶端(DHTML/CSS/JS/XML)與伺服端(設計模式/UML/Servlet/JDBC/EJB/框架)基本功才是硬道理。切勿濫用 AJAX,適時適所發揮其「無感知交互」優勢。