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   消息发送做完,加班写个博客,记录下我的小心机

猜你喜欢

转载自blog.csdn.net/sinat_39634657/article/details/81335952