package com.hoo.chat;
import java.util.Collection;
import java.util.Date;
import javax.servlet.ServletContext;
import org.directwebremoting.ScriptBuffer;
import org.directwebremoting.ScriptSession;
import org.directwebremoting.ServerContext;
import org.directwebremoting.ServerContextFactory;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.web.context.ServletContextAware;
import com.hoo.entity.Message;
@SuppressWarnings("unchecked")
public class ChatMessageClient implements ApplicationListener, ServletContextAware {
private ServletContext ctx;
public void setServletContext(ServletContext ctx) {
this.ctx = ctx;
}
@SuppressWarnings("deprecation")
public void onApplicationEvent(ApplicationEvent event) {
// 僅處理 ChatMessageEvent
if (event instanceof ChatMessageEvent) {
Message msg = (Message) event.getSource();
ServerContext context = ServerContextFactory.get();
// 獲取所有連接 chat.jsp 的 ScriptSession
Collection sessions = context.getScriptSessionsByPage(ctx.getContextPath() + "/chat.jsp");
for (ScriptSession session : sessions) {
ScriptBuffer sb = new ScriptBuffer();
Date time = msg.getTime();
String s = time.getYear() + "-" + (time.getMonth() + 1) + "-" + time.getDate() + " "
+ time.getHours() + ":" + time.getMinutes() + ":" + time.getSeconds();
// 構造 JavaScript 調用:showMessage({msg: '...', time: '...'})
sb.appendScript("showMessage({msg: '")
.appendScript(msg.getMsg())
.appendScript("', time: '")
.appendScript(s)
.appendScript("'})");
System.out.println(sb.toString());
// 向瀏覽器推送腳本執行
session.addScript(sb);
}
}
}
}
ApplicationListener → 容器發布事件時自動回調 onApplicationEvent;ServletContextAware → 獲取 ServletContext 以構建頁面路徑;instanceof ChatMessageEvent 過濾業務事件;ServerContextFactory.get() 獲取 DWR 服務端上下文;getScriptSessionsByPage("/chat.jsp") 精準定位所有在線聊天頁面會話;ScriptBuffer → 生成調用客戶端 showMessage(data) 的 JS 代碼;session.addScript(sb) 將腳本推送至瀏覽器執行 (Comet 長連接通道)。applicationContext-beans.xml<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="chatService" class="com.hoo.chat.ChatService"/>
<bean id="chatMessageClient" class="com.hoo.chat.ChatMessageClient"/>
</beans>
dwr.xml:暴露服務與類型轉換<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN"
"https://getahead.org/dwr/dwr30.dtd">
<dwr>
<allow>
<!-- Message 實體轉換器:僅序列化 msg、time 兩屬性 -->
<convert match="com.hoo.entity.Message" converter="bean">
<param name="include" value="msg,time"/>
</convert>
<!-- 以 Spring 容器創建 ChatService,暴露為 JavaScript ChatService -->
<create creator="spring" javascript="ChatService">
<param name="beanName" value="chatService"/>
</create>
</allow>
</dwr>
creator="spring":告訴 DWR 從 Spring 容器獲取 Bean,而非自行實例化;beanName="chatService":對應 Spring Bean id;convert match="...Message":自定義序列化策略,避免暴露敏感字段或循環引用;include="msg,time":僅傳輸業務必需字段,減小網絡負載。前置條件:
web.xml已配置DwrListener、DwrServlet(含pollAndCometEnabled=true)、ContextLoaderListener。詳細見系列第三篇。