深吸一口气,闷了这杯水,我来记录一下六个月来与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 οnclick=send()>点击发送</button>
</body>
好了,关于dwr的所有东西我都写完了。记得在我想放弃的时候,有位大哥曾经跟我说:就差那一下蹭一下就上去了。看似阻挡在你面前的是一座山,很高很险,当你翻过去了之后,它就成了一张纸,一张薄的不能再薄的纸。
展示一下我做出来的效果: 在左边窗口点击发送消息给用户123和用户1234,会同时在两个窗口的消息图标上加1,而且是在不大叔刷页面的情况下。
2018.8.1 消息发送做完,加班写个博客,记录下我的小心机