1. 程式人生 > >DWR框架的初次使用及經驗總結

DWR框架的初次使用及經驗總結

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);

    }

}