由于项目中最近需要用到dwr实现一些功能,因此在网上和dwr官网上找了一些资料进行学习。在此记录一下。(此处实现简单的dwr应用和dwr消息反向推送

一、引入dwr的包

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

二、引入spring的包,因为示例代码中和spring进行了整合,spring的包略。

三、spring的配置文件(启用注解扫描即可

<context:component-scan base-package="com.huan.dwr" />

四、修改web.xml

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.directwebremoting.servlet.DwrListener</listener-class>
</listener>
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<display-name>DWR Servlet</display-name>
<description>Direct Web Remoter Servlet</description>
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
<init-param>
<param-name>fileUploadMaxBytes</param-name>
<param-value>1024000</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>accessLogLevel</param-name>
<param-value>runtimeexception</param-value>
</init-param>
<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>jsonRpcEnabled</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>jsonpEnabled</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>preferDataUrlSchema</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>org.directwebremoting.extend.ScriptSessionManager</param-name>
<param-value>com.huan.dwr.simple.reverseajax.DwrScriptSessionManager</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>

注:1.测试环境中可以将debug的参数改为true,开发环境改为false

          2.fileUploadMaxBytes 文件上传时限制上传文件的大小

3.org.directwebremoting.extendScriptSessionManager 为修改dwr默认的scriptSession的管理,默认情况下,页面上每刷新一次,都将会产生一次scriptsession,这样会产生没有的 scriptsession,浪费服务器的资源。而HttpSession只在用户第一次访问服务器时产生,所以可以考虑使用httpSession和 ScriptSession结合管理scriptsession.即需要重写dwr ScriptSessionManager接口中的方法

五、dwr的配置(默认会找web-inf 下的dwr.xml文件)

六、简单的dwr实例应用

1.jsp页面引入dwr需要的js文件

<script type="text/javascript" src="${pageContext.request.contextPath }/dwr/engine.js"></script> <!--  dwr自动生成 -->
<script type="text/javascript" src="${pageContext.request.contextPath }/dwr/util.js"></script><!--  dwr自动生成 ,dwr的一些工具类-->
<!-- SimpleDwrTest.js 这个为dwr.xml文件中create 标签中javascript元素的值 -->

<script type="text/javascript" src="${pageContext.request.contextPath }/dwr/interface/SimpleDwrTest.js"></script>

2.jsp页面的代码

<strong><%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>测试dwr简单的功能</title>
<script type="text/javascript" src="${pageContext.request.contextPath }/dwr/engine.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath }/dwr/util.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath }/dwr/interface/SimpleDwrTest.js"></script>
<script type="text/javascript">
function method1(){
SimpleDwrTest.noArgumentMethod();
}
function method2(){
SimpleDwrTest.hellowArgument("一个参数.");
}
function method3(){
SimpleDwrTest.invokedMoreArgument("参数一","参数二");
}
/** 获取到后台返回的值,只需要在回调函数中处理即可 */
function method4(){
SimpleDwrTest.returnValue("传递值到后台",function(r){
alert(r);
});
SimpleDwrTest.returnValue("传递值到后台",{
callback : function(r){
alert(r+"...");
}
});
}
/** 需要在dwr.xml文件中配置一下,才可以得到详细的异常信息 */
function method5(){
SimpleDwrTest.handleError({
errorHandler : function(msg,e){
alert(msg);
}
});
}
/** 处理实体类 */
function method6(){
var student = {
username : 'huan',
age : 23,
address : '湖北黄冈.'
};
SimpleDwrTest.addStudy(student,function(r){ alert(r); });
}
function method7(){
var file = document.getElementById('file');
SimpleDwrTest.fileUpload("ok",file,function(r){
alert(r);
});
}
</script>
</head>
<body>
<div>
<ul>
<li>调用无参方法:<input type="button" value="click" onclick="method1()"> </li>
<li>调用一个参数的方法:<input type="button" value="click" onclick="method2()"/> </li>
<li>调用多个参数的方法:<input type="button" value="click" onclick="method3()"/> </li>
<li>后台返回值到前台:<input type="button" value="click" onclick="method4()"/> </li>
<li>处理实体类的信息:<input type="button" value="click" onclick="method6()"/></li>
<li>处理异常信息:<input type="button" value="click" onclick="method5()"/></li>
<li>实现简单的文件上传:<input id="file" type="file" /><input type="button" value="click" onclick="method7()"/> </li>
</ul>
</div>
</body>
</html></strong>

 2.后台对应的java代码

<strong>package com.huan.dwr.simple;

import java.io.File;
import java.io.IOException; import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.directwebremoting.io.FileTransfer;
import org.springframework.stereotype.Component; import com.huan.dwr.simple.data.Study;
/**
* 测试一下dwr调用简单的java方法
*
* @描述
* @作者 huan
* @时间 2016年4月11日 - 下午7:11:02
*/
@Component("simpleDwrTest")
public class SimpleDwrTest {
/**
* 调用无参数的构造方法
*/
public void noArgumentMethod() {
System.out.println("invoked...");
}
/**
* 调用一个参数的方法
*
* @param hello
*/
public void hellowArgument(String hello) {
System.out.println(hello + " world.");
}
/** 调用多个参数的方法 */
public void invokedMoreArgument(String param1, String param2) {
System.out.println(String.format("这是接收到的参数:[%s]-[%s]", param1, param2));
}
/**
* 后台返回值到前台
*
* @param value
* @return
*/
public String returnValue(String value) {
return "后台返回的值:" + value;
}
/**
* 处理错误信息
*/
public void handleError() {
System.out.println("该方法将会抛出异常");
throw new RuntimeException("后台出异常了.");
}
/**
* 以实体类作为参数
* @param study
* @return
*/
public String addStudy(Study study) {
System.out.println(study);
return "添加学生成功!!!";
}
/**
* 文件上传
*
* @param fileName
* @param flie
* @return
* @throws IOException
*/
public String fileUpload(String msg,FileTransfer fileTransfer) throws IOException {
try {
System.out.println(fileTransfer.getFilename());
System.out.println(fileTransfer.getMimeType());
System.out.println(fileTransfer.getSize());
System.out.println(fileTransfer.getOutputStreamLoader());
FileUtils.copyInputStreamToFile(fileTransfer.getInputStream(), new File("D:" + File.separator + fileTransfer.getFilename()));
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(fileTransfer.getInputStream());
}
return "文件上传成功.";
}
}
</strong>

 可以看到,使用了dwr后,可以使访问后台,变得简单了。  比如文件的上传也变得简单了。

 注意:文件的上传需要依赖  commons-fileupload-version.jar这个jar包。

 在项目中有时需要用到后台发生了变化,需要及时通知到前台,这个可以使用dwr的来实现。

 注意: 由 于scriptSession比较特殊,页面每次刷新都会创建一个scriptsession,这个不符合我们的需求,应当只需要一个 scriptSession即可。然后我们知道httpsession是第一次访问服务器时创建的,并且在整个应用中只有一个,所以可以使用 httpsession的结合scriptsession做一些事情。

在dwr3中提供了ScriptSessionListener用于 监听scriptsession的创建和销毁。因此,我们创建一个类实现ScriptSessionListener接口,在这个类中维护一个 map,map的key为httpsession的id,值为Scriptsession.

步骤:

一、写一个类实现ScriptSessionListener接口,在此接口中实现自己维护scriptsession

public class HandleScriptSessionLinstener implements ScriptSessionListener {
private static final ConcurrentHashMap<String, ScriptSession> SCRIPT_SESSIONS = new ConcurrentHashMap<String, ScriptSession>();
/**
* ScriptSession 创建时触发
*/
@Override
public void sessionCreated(ScriptSessionEvent ev) {
String sessionId = WebContextFactory.get().getSession().getId();
SCRIPT_SESSIONS.put(sessionId, ev.getSession());
}
/**
* ScriptSession销毁时触发
*/
@Override
public void sessionDestroyed(ScriptSessionEvent ev) {
SCRIPT_SESSIONS.remove(WebContextFactory.get().getSession().getId());
}
/** 获取所有的scriptsession */
public static Collection<ScriptSession> getAllSctiptSessions() {
return SCRIPT_SESSIONS.values();
}
}

二、写一个类继承默认的scriptsession管理器DefaultScriptSessionManager,在构造方法中注入上一步自己写的scriptsessionlistener,然后重写获取scriptsession的方法

public class DwrScriptSessionManager extends DefaultScriptSessionManager {
/**
* 注入自己的scriptsession管理
*/
public DwrScriptSessionManager() {
this.addScriptSessionListener(new HandleScriptSessionLinstener());
}
@Override
public Collection<ScriptSession> getAllScriptSessions() {
return HandleScriptSessionLinstener.getAllSctiptSessions();
}
}

三、在web.xml配置文件中进行配置(DwrServlet参数中进行配置)

<init-param>
<param-name>org.directwebremoting.extend.ScriptSessionManager</param-name>
<param-value>com.huan.dwr.simple.reverseajax.DwrScriptSessionManager</param-value>
</init-param>

四、写后台推送的业务逻辑,此处简单的实现为,每隔5秒中向前台推送一个数据

package com.huan.dwr.simple.reverseajax;

import java.util.Random;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import org.directwebremoting.Browser;
import org.directwebremoting.ScriptSession;
import org.directwebremoting.ScriptSessionFilter;
import org.directwebremoting.ScriptSessions;
import org.directwebremoting.WebContext;
import org.directwebremoting.WebContextFactory;
import org.directwebremoting.extend.UninitializingBean;
import org.springframework.stereotype.Component;
/**
* 推送消息到客户端
*
* @描述
* @作者 huan
* @时间 2016年4月11日 - 下午9:05:49
*/
@Component("pushMessage2Client")
public class PushMessage2Client implements Runnable, UninitializingBean {
private ScheduledThreadPoolExecutor threadPool = null;
/** 保存在scriptsession中的属性 */
private static final String LOGIN_NAME = "LOGIN_NAME";
private Random random = new Random();
public PushMessage2Client() {
threadPool = new ScheduledThreadPoolExecutor(1);
/**
* 每隔5秒推送数据到前台客户端
*/
threadPool.scheduleAtFixedRate(this, 1, 5, TimeUnit.SECONDS);
} @Override
public void run() {
final int randomNumber = random.nextInt(5000);
Browser.withAllSessionsFiltered(new ScriptSessionFilter() {
@Override
public boolean match(ScriptSession session) {
System.out.println("登录名为:" + session.getAttribute(LOGIN_NAME));
return true;
}
}, new Runnable() {
@Override
public void run() {
/**
* 调用客户端的show方法,并将randomNumber作为参数
* 如果上方那个过滤器返回true:则此方法调用
* 返回false:则此方法不调用
*/
ScriptSessions.addFunctionCall("show", randomNumber);
}
});
} /** 添加属性到scriptSession中 */
public void addScriptSessionAttribute(String loginName) {
WebContext webContext = WebContextFactory.get();
ScriptSession scriptSession = webContext.getScriptSession();
scriptSession.setAttribute(LOGIN_NAME, loginName);
}
@Override
public void destroy() {
if (null != threadPool) {
threadPool.shutdown();
}
}
}

五、前台jsp的写法:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>测试dwr简单的功能</title>
<script type="text/javascript" src="${pageContext.request.contextPath }/dwr/engine.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath }/dwr/util.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath }/dwr/interface/PushMessage2Client.js" ></script>
<script type="text/javascript">
function start(){
var loginName = document.getElementById('loginName');
if(!loginName){
alert("请输入登录名.");
return ;
}
document.getElementById('loginName').style.disabled=true;
dwr.engine.setActiveReverseAjax(true);
dwr.engine.setNotifyServerOnPageUnload(true);
PushMessage2Client.addScriptSessionAttribute(loginName.value);
}
/** 接收后台的数据,加入到前台页面 */
function show(num){
document.getElementById('show').innerHTML += num+",";
}
</script>
</head>
<body>
<div>
<input type="text" id="loginName" /><input type="button" onclick="start()" value="链接"/>
<textarea rows="10" cols="100" id="show"></textarea>
</div>
</body>
</html>

到此,一个简单的dwr运用和dwr反向ajax消息推送就实现了,如有那些地方写错了,欢迎指出。

dwr简单应用及一个反向ajax消息推送的更多相关文章

  1. 基于ajax与msmq技术的消息推送功能实现

    周末在家捣鼓了一下消息推送的简单例子,其实也没什么技术含量,欢迎大伙拍砖.我设计的这个推送demo是基于ajax长轮询+msmq消息队列来实现的,具体交互过程如下图: 先说说这个ajax长轮询,多长时 ...

  2. asp.net mvc 实现简单的实时消息推送

    因为项目需要,需要在网页上实现消息的推送.在百度上搜索了一下,发现实现网页上的消息推送,可以使用asp.net 中的SignalR类库,当然也可以使用H5的WebSocket  Ajax的轮回.当然此 ...

  3. 基于XMPP协议(openfire服务器)的消息推送实现

    转自:http://blog.csdn.net/nomousewch/article/details/8088277 最近好像有不少朋友关注Android客户端消息推送的实现,我在之前的项目中用到过J ...

  4. service worker 消息推送

    https://developers.google.com/web/fundamentals/codelabs/push-notifications/?hl=en 首先下载源码: git clone ...

  5. Java对接微信公众号模板消息推送

    内容有点多,请耐心! 最近公司的有这个业务需求,又很凑巧让我来完成: 首先想要对接,先要一个公众号,再就是开发文档了:https://developers.weixin.qq.com/doc/offi ...

  6. dwr消息推送和tomcat集群

    网友的提问: 项目中用到了dwr消息推送.而服务端是通过一个http请求后 触发dwr中的推送方法.而单个tomcat中.服务器发送的http请求和用户都在一个tomcat服务器中.这样就能精准推送到 ...

  7. dwr消息推送

    闲来无事,把自己关于对dwr消息推送的实现过程描述一番. 首先第一步,当然在工程中是加入dwr.jar了,接着在web.xml中配置以下代码 <servlet> <servlet-n ...

  8. Netty实现一个简单聊天系统(点对点及服务端推送)

    Netty是一个基于NIO,异步的,事件驱动的网络通信框架.由于使用Java提供 的NIO包中的API开发网络服务器代码量大,复杂,难保证稳定性.netty这类的网络框架应运而生.通过使用netty框 ...

  9. MQTT是IBM开发的一个即时通讯协议,构建于TCP/IP协议上,是物联网IoT的订阅协议,借助消息推送功能,可以更好地实现远程控制

    最近一直做物联网方面的开发,以下内容关于使用MQTT过程中遇到问题的记录以及需要掌握的机制原理,主要讲解理论. 背景 MQTT是IBM开发的一个即时通讯协议.MQTT构建于TCP/IP协议上,面向M2 ...

随机推荐

  1. shell逐行读取文件内容

    shell 中逐行读取文件内容 1.语法简介 #!/bin/bash <<EOF shell 中逐行读取文件内容的语法如下所示. 这里虽然很简单,但是再配合上其他的工具,如sed,awk, ...

  2. word域实现动态填充信息附件下载

    1.问题描述:在页面上一些下载附件功能,点击触发执行下载操作时候,有些电脑的浏览器可以,有些电脑的浏览器下载不了,电脑打开弹出的下载框下载的不是一个文件,而是一个如jspx后缀名的页面,jspx后缀是 ...

  3. Spring5(七)——AOP注解

    一.AOP注解 1.介绍 上一节介绍了 AspectJ 框架如何实现 AOP,具体的实现方式是通过 xml 来进行配置的.xml 方式思路清晰,便于理解,但是书写过于麻烦.这一节介绍注解的方式来进行 ...

  4. FastAPI(7)- get 请求 - 详解 Path

    前言 上一篇讲了可以为查询参数添加额外的校验和元数据,Query 库:https://www.cnblogs.com/poloyy/p/15306809.html 这篇讲可以为路径查询添加额外的校验和 ...

  5. 离散化模板题 II ——重复元素离散化后的数字不相同

    离散化模板题 II --重复元素离散化后的数字不相同 题目描述 现有数列A1, A2, ⋯, An,数列中可能有重复元素. 现在要求输出该数列的离散化数列,重复元素离散化后的数字不相同. 输入 第一行 ...

  6. Java基础系列(26)- 打印三角形

    package struct; public class TestDemo { public static void main(String[] args) { for (int i = 1; i & ...

  7. 一文让你彻底理解SQL关联子查询

    员工表的主要信息: 需求:检索工资大于同职位的平均工资的员工信息. 直觉的做法 员工多,而相应的职位(如销售员.经理.部门经理等)少,因此首先想到的思路是对职位分组,这样就能分别得到各个职位的平均工资 ...

  8. LR集合点策略

    给大家分享一个LR集合点策略,跑并发脚本时,一定要设置策略,要不然得出的响应时间无意义.默认选择第一个(当所有虚拟用户中的x % 到达集合点进释放,即仅当指定百分比的虚拟用户到达集合点时,才释放虚拟用 ...

  9. eval(input())

    看到一段代码,判读输入的数字,用的是eval(input()),查了一下,原来input()会把所有输入值,包括数字,视为字符串,而eval()会去掉字符串最外层的引号,然后当做Python语句执行[ ...

  10. P4173-残缺的字符串【FFT】

    正题 题目链接:https://www.luogu.com.cn/problem/P4173 题目大意 给出两个字符串\(S,T\),其中包含小写字母和一些\(?\),\(?\)可以匹配任何字符. 求 ...