DWR框架的初次使用及經驗總結
阿新 • • 發佈:2018-12-06
DWR的宣傳語是 “ Easy Ajax For Java”。
需求是這樣的--後端定時接受伺服器傳送過來的資訊。並把資訊每隔五秒推送一次到前端實現頁面區域性重新整理功能!
AJAX可是實現前端非同步傳送請求到後端,拿取資料,並實現頁面區域性重新整理的功能!
Ajax有一個很大的缺陷就是“無法滿足傳統桌面系統的需求——伺服器端需要向客戶端主動傳送訊息”。服務端推送技術的應用場景有很多!
DWR框架技術可以實現即時推送後端資料到客戶端。
因為這個功能。我是幫別人做的。他用的框就是springmvc.也沒用maven做管理。所以步驟如下:
1:引入jar包 dwr.jar commons-logging-1.1.3.jar quartz-2.3.0.jar quartz-jobs-2.2.3.jar spring-context-support-4.0.0.RELEASE.jar 2:配置檔案配置相關DWR框架支援 web.xml配置。配置類似DispatchServlet的配置 <!-- dwr配置資訊start --> <servlet> <!-- 指定DWR核心Servlet的名字 --> <servlet-name>dwr</servlet-name> <!-- 指定DWR核心Servlet的實現類 --> <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class> <!-- 指定DWR核心Servlet處於除錯狀態 --> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> <!-- 設定使用反向Ajax技術 --> <init-param> <param-name>activeReverseAjaxEnabled</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>initApplicationScopeCreatorsAtStartup</param-name> <param-value>true</param-value> </init-param> <init-param> <!--長連線只保持時間 --> <param-name>maxWaitAfterWrite</param-name> <param-value>60</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- 指定核心Servlet的URL對映 --> <servlet-mapping> <servlet-name>dwr</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping> <!-- dwr配置資訊end --> <!--對靜態檔案和頁面不攔截--> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.css</url-pattern> </servlet-mapping> dwr.xml檔案配置。放在和web.xml同目錄。 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://getahead.org/dwr/dwr20.dtd"> <dwr> <!-- DWR可以建立和轉換的類 --> <allow> <!-- 指定用哪種創造器 --> <create javascript="Message" creator="new" scope="application"><!-- application --> <include method="addMessage"/> <!--只對前端開房addMessage方法--> <param name="class" value="com.zukai.test.Message"></param> </create> </allow> </dwr>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd"> <!-- <bean id="udpClient" class="com.zukai.connection.udp.UDPClient" init-method="recv"/> --> <!-- 業務實體 --> <bean name="quartzTest" class="com.zukai.test.QuartzTest" init-method="recv"/> <!-- 定義定時任務 --> <bean id="quartzTestJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="quartzTest"></property><!-- 目標物件 --> <property name="targetMethod" value="pushRefresh"></property><!-- 目標方法 --> <property name="concurrent" value="false"></property><!-- 多job併發設定 --> </bean> <!-- 定義觸發器 --> <bean id="quartzTestTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"> <property name="jobDetail" ref="quartzTestJob"/> <!--延時多少秒後執行,這裡不延時 0秒後執行 --> <property name="startDelay" value="0" /> <!-- 每隔5秒重複執行 --> <property name="repeatInterval" value="5000" /> </bean> <!-- 定義定時排程 --> <bean name="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="quartzTestTrigger" /> </list> </property> </bean> </beans>
上面是引入定時任務的配置資訊。每5秒執行一次沖服務器獲取資料資訊。程式碼如下:
package com.zukai.test; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; /** *author:liyy *date:2018年10月9日 *描述資訊: */ @Component public class QuartzTest { public static Logger logger = LoggerFactory.getLogger(QuartzTest.class); public static Map<String,Object> mapCache = new ConcurrentHashMap<>(); public static DatagramSocket ds = null; //每隔五秒呼叫一次,獲取資料推送到頁面 public void pushRefresh() throws IOException, InterruptedException { Message mg = new Message(); String message = null; if(mapCache.containsKey("message")){ message = (String)mapCache.get("message"); mg.addMessage("admin", message+"瓦"+","+message+"度"); } } //獲取UDP伺服器傳送的資料,並存儲到mapCache裡面。 public void recv(){ new Thread(new ReceiveThread()).start(); } public void schedule(){ //注意這裡就是可以進行資料庫的查詢操作,可以將查詢需要推送的資訊放到第二個引數,第一個引數自然是我們要指定推送的表示使用者 Message mg = new Message(); for(int i=0;i<100;i++){ try { Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } mg.addMessage("admin", i+1000+"瓦"+","+i+30+"度"); } } private String bytesToHex(byte[] bytes, int begin, int end) { StringBuilder hexBuilder = new StringBuilder(2 * (end - begin)); for (int i = begin; i < end; i++) { hexBuilder.append(Character.forDigit((bytes[i] & 0xF0) >> 4, 16)); // 轉化高四位 hexBuilder.append(Character.forDigit((bytes[i] & 0x0F), 16)); // 轉化低四位 } return hexBuilder.toString().toUpperCase(); } public static Long HexToDecimalism(String hexNum){ Long decNum = Long.parseLong(hexNum,16); return decNum; } class ReceiveThread implements Runnable{ @Override public void run() { // TODO Auto-generated method stub logger.info("接受資料開始......"); //DatagramSocket ds = null; try { if(ds==null){ ds = new DatagramSocket(2000);// UDP通訊類 2000為埠號 } } catch (SocketException e1) { // prompt("本地接收埠已被使用"); logger.error("本地接收埠已被使用"); System.exit(0); } while (true) { byte[] buf = new byte[1024]; DatagramPacket dp = new DatagramPacket(buf, buf.length); // 接收資料 try { ds.receive(dp); String ip = dp.getAddress().getHostAddress();// ip地址 int port = dp.getPort();// 返回接收或傳送該資料報文的遠端主機埠號。 String text = bytesToHex(dp.getData(),0,dp.getLength()); //String text = new String(dp.getData(), 0, dp.getLength()); // 獲取的串列埠資料 if (text.equals("exit")) { System.out.println(ip + "退出會話......"); break; } System.out.println(ip + ":" + port + "===>me " + text); mapCache.put("message", text); }catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ //ds.close(); } } } } }
前端頁面定時獲取資料。重新整理
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript" src="js/engine.js"></script>
<script type="text/javascript" src="js/util.js"></script>
<script type="text/javascript" src="js/Message.js"></script>
<script type="text/javascript" src="js/jquery-1.4.2.js"></script>
<script type="text/javascript">
var chatlog = "";
//傳送資訊
/* function sendMessage() {
var message = $("#message").val();
var user = $("#user").val();
Message.addMessage(user, message);
} */
//接收資訊
function receiveMessages(messages) {
var lastMessage = messages;
/* chatlog = "<div>" + lastMessage + "</div>" + chatlog; */
electricity = lastMessage.split(",")[0];
temperature = lastMessage.split(",")[1];
dwr.util.setValue("showElectricity",electricity, {
escapeHtml : false
});
dwr.util.setValue("showTemperature", temperature, {
escapeHtml : false
});
}
//讀取name值作為推送的唯一標示
function onPageLoad(){
var userId = getQueryString("name");
/* $("#myName").html(userId); */
Message.onPageLoad(userId);
}
//獲取url中的引數
function getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]);
return null;
}
//一上來就載入onPageLoad()方法,將讀取的name作為唯一標識,這裡不一定要從url中取出name作為識別符號,只要是該頁面唯一的資料都可以是識別符號
$(document).ready(function(){
dwr.engine.setActiveReverseAjax(true);//使用ajax反向代理
dwr.engine.setNotifyServerOnPageUnload(true);//服務啟動直接載入
onPageLoad();
});
</script>
</head>
<body>
<!-- 我是<span id="myName" style="color:red"></span><br/>
推送給下面這位user<br/>
user:<br/>
<input id="user" type="text" /><br/>
推送資訊為:<br/>
<input id="message" type="text" value="hey" />
<input type="button" value="send" onclick="sendMessage()" />
<br> -->
<!-- <div id="list"></div> -->
<div style="height: 760px;width: 100%;">
<div style="height: 180px;width: 100%;text-align:center;">
電流:<input id="showElectricity" type="text" value="" style="width: 440px;height: 60px;">
</div>
<div style="height: 180px;width: 100%;text-align: center;">
溫度:<input id="showTemperature" type="text" value="" style="width: 440px;height: 60px;">
</div>
</div>
</body>
</html>
package com.zukai.test;
/**
*author:liyy
*date:2018年10月9日
*描述資訊:
*/
import java.util.Collection;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpSession;
import org.directwebremoting.Browser;
import org.directwebremoting.ScriptBuffer;
import org.directwebremoting.ScriptSession;
import org.directwebremoting.ScriptSessionFilter;
import org.directwebremoting.WebContextFactory;
public class Message{
public void addMessage(String userid, String message) {
final String userId = userid;
final String autoMessage = message;
System.out.println("To:" + userid + ",Msg:" + message);
Browser.withAllSessionsFiltered(new ScriptSessionFilter() {
public boolean match(ScriptSession session) {
if (session.getAttribute("name") == null)
return false;
else
return (session.getAttribute("name")).equals(userId);
}
}, new Runnable() {
private ScriptBuffer script = new ScriptBuffer();
public void run() {
script.appendCall("receiveMessages", autoMessage);
Collection<ScriptSession> sessions = Browser
.getTargetSessions();
for (ScriptSession scriptSession : sessions) {
if(scriptSession.getAttribute("name").equals(userId)){
scriptSession.addScript(script);
break;
}
}
}
});
}
//頁面載入直接執行該方法
public void onPageLoad(String name) {
HttpSession session = WebContextFactory.get()
.getSession();
session.setAttribute("name", name);
WebContextFactory.get().getScriptSession().setAttribute("name", name);
}
}