DWR——我的職業生涯故事線

深吸一口氣,悶了這杯水,我來記錄一下六個月來與DWR的恩恩怨怨!

2018.3   來到一個新公司(缺人),當時給我一個消息發送的模塊讓我做(我還處在剛剛看完java基礎),讓我用DWR做消息發送

2018.5   在這兩個月期間,斷斷續續的在看網上的各種博客,論壇。這裏吐槽一下自己查資料的水平(已經對各種轉發的技術博客無感,再也不會一股腦兒的上去就看它怎麼寫了。真的是既浪費時間又什麼幫助都沒有)

2018.6   這個月趕上大學畢業,已經再無心思研究消息怎麼發送(不會DWR,其實在逃避)

2018.7   領導讓我繼續做消息發送,沒人能替我寫

-----------------------------------------------------------------------------我是正文-----------------------------------------------------------------------------

簡單的DWR案例網上一搜一大片,我就不多廢話的;我要講的是 把DWR3.0和Spring4.0進行整合。 

首先在我是maven項目,在pom.xml中導入 dwr,網上說還要導入commons-logging,親測沒有沒影響,有log4j就行

<dependency>
            <groupId>org.directwebremoting</groupId>
            <artifactId>dwr</artifactId>
            <version>3.0.2-RELEASE</version>
 </dependency>

<dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.3</version>
        </dependency>

官網上將,dwr整合spring有兩種,一是在直接在spring.xml文件中加入namespace,第二種是建一個新的dwrservlet

只能怪我看不懂英文,用不會第一種方式,所以我用的是第二種,在WEB-INFO文件夾下建立一個dwr.xml文件與web.xml在同一個目錄下。

那麼好了,我們現在先來配置web.xml文件。

首先說一下,我們在web.xml文件裏到底配置的是什麼呢?(就因爲我對框架的原理不熟,導致我無腦的粘貼網上的配置文件,都不知道自己錯哪了)

 

web.xml 中有關dwr的配置

<servlet>

<!--將靜態資源交由 dwr-invoker 下面的class類處理 -->
      <servlet-name>dwr-invoker</servlet-name>
      <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
      <init-param>

<!--debug 就是用來讓你調試的,如果你的dwr配置好了,運行項目後你就能看到在localhost:8080/projectNaem/dwr下會有你在dwr.xml中暴露的類,沒有就說明你的配置有問題-->
          <param-name>debug</param-name>
          <param-value>true</param-value>
      </init-param>
     <init-param>

<!--我在啓動tomcat的時候總會報錯,錯誤是Missing config file: 'WEB-INF/dwr-*.xml' 這個問題肯定是你配置有問題,我的WEB-INFO下肯定有dwr.xml文件,但是它就是給你報錯,那你就先加上這句,它的意思就是加載配置文件,路徑是/WEB-INF/dwr.xml,如果你不寫這個的話系統默認也會去找你在WEB-INFO下的dwr.xml文件,除非你改名或者有多個dwr.xml文件,那它就真找不到了-->
        <param-name>config</param-name>
        <param-value>/WEB-INF/dwr.xml</param-value>
        </init-param>
         <init-param>

<!--這句話我一開始沒寫,沒寫的後果是什麼呢,就是你的前臺頁面執行不了反向ajax,也就是我走到最後給特定的session發送scriptSession.addScript(script)時,構造的jsp代碼無法傳遞給前臺,這個坑實在是太大了,必須標紅啊-->
        <param-name>activeReverseAjaxEnabled</param-name>
        <param-value>true</param-value>
        </init-param>
    </servlet>
<!--下面這句話的意思,就是說我要攔截靜態文件,那這個靜態文件的攔截是什麼規則呢,就是dwr開頭,後面的所有url都攔截,它攔截了幹嘛用?攔截了給上面的servlet-class,很明顯servlet-class是dwr.jar包裏的東西,是用來生成engine.js和util.js用的。哦,當然還有interface/你想暴露的.js。所以要是攔截不到,那麼你的頁面上肯定就會報404,找不到這幾個.js文件。我相信很多人在用spring整合dwr時候都會遇到這個問題,原因主要還是你頁面的src路徑寫的不對,打個正確的比方 http://localhost:8080/ProjectName/dwr/engine.js,網上有人說是什麼springmvc的攔截器給誤攔截了,因爲springmvc配置的時候配的規則是  <url-pattern>/</url-pattern>,那就要看你暴露的類怎麼寫了,要是你寫在controller裏,那也出問題了,其他沒影響,不過保險起見,你可以把dwr的配置信息全部放在springmvc的前面。-->

<servlet-mapping>
        <servlet-name>dwr-invoker</servlet-name>
        <url-pattern>/dwr/*</url-pattern>
    </servlet-mapping>

dwr.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC
    "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN"
    "http://getahead.org/dwr/dwr30.dtd">
<dwr>
<allow>
    <create javascript="Message" creator="new" scope="application"><!-- application -->  
        <param name="class" value="com.dwr.Message"></param>  
    </create> 
</allow>
</dwr>

有關dwr.xml出錯,網上的答案也是夠五花八門的,我一個個試過來,一個個錯過去。

錯誤答案1:有說在application.xml中配置要暴露的bean,然後再在dwre.xml中修改配置。

 <create javascript="Message" creator="spring" ><!-- application -->  
        <param name="beanName" value="Message"></param>  那種方式我覺得太麻煩,最討厭的就是在配置文件里加東西了,直接拿出來寫,或者加註解多方便。

錯誤答案2::還有說<!DOCTYPE dwr PUBLI  "-//GetAhead LimiteRemo3.0//EN""http://getahead.org/dwr/dwr30.dtd"> 這個有問題的,要改成 10.dtd,這個答案我一直沒看懂,覺得就是在渾水。很煩

接下來,把消息發送的java類寫一下

package com.dwr;

import java.util.Collection;

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 ids , String message) {
        final String userId = ids;
        final String autoMessage = message;
        System.out.println("To:" + userId + ",Msg:" + autoMessage);    
         //執行推送
         //注意這裏調用了有filter功能的方法
        //如果我們不想要給所有的客戶端 推送消息,只想給特定的客戶端推送,那麼我們可以使用 ScriptSessionFilter來實現。
        //在filter中去判定session中的Attribute值是不是我們給定的。        
        // Browser. withAllSessionsFiltered(filter, run);    //注意這裏調用了有filter功能的方法
        // 下面的函數相當於上面的擴展
        Browser.withAllSessionsFiltered(new ScriptSessionFilter() {     
            public boolean match(ScriptSession session) {
                if (session.getAttribute("name") == null)
                    return false;
                else {
                     String attribute = (String) session.getAttribute("name");  
                     return (userId.contains(attribute));  
                }                                                   
            }            
        }, new Runnable() {
                private ScriptBuffer script = new ScriptBuffer();
                /*
                    script.appendCall("receiveMessages", autoMessage);
                     其中receiveMessages爲在想推送的頁面中的javascript方法,autoMessage是這個方法的參數,
                    這樣那個頁面就能得到推送的內容了,至於如何展現,就看你的需要了。
                 */                    
                public void run() {
                    script.appendCall("show", autoMessage);  
                    Collection<ScriptSession> sessions = Browser.getTargetSessions(); //取得所有的頁面訪問者
                    for (ScriptSession scriptSession : sessions) {        //遍歷取得對應用戶的 scriptsession
                        scriptSession.addScript(script);
                        System.out.println("userid---"+userId);
                    }
                }
            });
        }
        public void onPageLoad(String name) {
        HttpSession session = WebContextFactory.get()
                .getSession();
        session.setAttribute("name", name);
        WebContextFactory.get().getScriptSession().setAttribute("name", name);
        System.out.println(name +"---" + session);

    }

}

我寫代碼有個毛病,是個英文就要翻譯一下寫在旁邊,希望大家能看懂。網上大多關於這部分的內容也沒問題。

下面把消息發送的前端代碼寫一下

<!-- dwr -->.

<c:set var="ctx" value="${pageContext.request.contextPath}"/>

<script src="${ctx}/static/jquery-2.1.1.js"></script>

<script type="text/javascript" src="${ctx}/dwr/engine.js"></script>
<script type="text/javascript" src="${ctx}/dwr/util.js"></script>
<script type="text/javascript" src="${ctx}/dwr/interface/Message.js"></script>
<script type="text/javascript">
    function init(){
        dwr.engine.setActiveReverseAjax(true);
        dwr.engine.setNotifyServerOnPageUnload(true);
        onPageLoad();
    }
    window.onload = init;
    function onPageLoad(){
        var userId = ${User.id};//獲取當前用戶的id
        Message.onPageLoad(userId);//把當前用戶的id作爲唯一標識傳遞給後臺生成一個Scriptsession
     }

function send(){

Message.addMessage(userId,message);//這裏是省略寫了,userId和message都是你要傳遞到後臺的參數,可以用jquery或者document.getelementbyid()的方法獲取具體值。

}

//這個是你在暴露的java類中寫的scriptbuffer
    function show(message){
        alert("新消息提醒");
    }
</script>
<body>

<button onclick=send()>點擊發送</button>

</body>

好了,關於dwr的所有東西我都寫完了。記得在我想放棄的時候,有位大哥曾經跟我說:就差那一下蹭一下就上去了。看似阻擋在你面前的是一座山,很高很險,當你翻過去了之後,它就成了一張紙,一張薄的不能再薄的紙。

展示一下我做出來的效果: 在左邊窗口點擊發送消息給用戶123和用戶1234,會同時在兩個窗口的消息圖標上加1,而且是在不大叔刷頁面的情況下。

 

2018.8.1   消息發送做完,加班寫個博客,記錄下我的小心機

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章