由于项目中最近需要用到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页面的代码
<%@ 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>
2.后台对应的java代码
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 "文件上传成功."; } }
可以看到,使用了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消息推送就实现了,如有那些地方写错了,欢迎指出。
相关推荐
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
MMC整流器技术解析:基于Matlab的双闭环控制策略与环流抑制性能研究,Matlab下的MMC整流器技术文档:18个子模块,双闭环控制稳定直流电压,环流抑制与最近电平逼近调制,优化桥臂电流波形,高效并网运行。,MMC整流器(Matlab),技术文档 1.MMC工作在整流侧,子模块个数N=18,直流侧电压Udc=25.2kV,交流侧电压6.6kV 2.控制器采用双闭环控制,外环控制直流电压,采用PI调节器,电流内环采用PI+前馈解耦; 3.环流抑制采用PI控制,能够抑制环流二倍频分量; 4.采用最近电平逼近调制(NLM), 5.均压排序:电容电压排序采用冒泡排序,判断桥臂电流方向确定投入切除; 结果: 1.输出的直流电压能够稳定在25.2kV; 2.有功功率,无功功率稳态时波形稳定,有功功率为3.2MW,无功稳定在0Var; 3.网侧电压电流波形均为对称的三相电压和三相电流波形,网侧电流THD=1.47%<2%,符合并网要求; 4.环流抑制后桥臂电流的波形得到改善,桥臂电流THD由9.57%降至1.93%,环流波形也可以看到得到抑制; 5.电容电压能够稳定变化 ,工作点关键词:MMC
Boost二级升压光伏并网结构的Simulink建模与MPPT最大功率点追踪:基于功率反馈的扰动观察法调整电压方向研究,Boost二级升压光伏并网结构的Simulink建模与MPPT最大功率点追踪:基于功率反馈的扰动观察法调整电压方向研究,Boost二级升压光伏并网结构,Simulink建模,MPPT最大功率点追踪,扰动观察法采用功率反馈方式,若ΔP>0,说明电压调整的方向正确,可以继续按原方向进行“干扰”;若ΔP<0,说明电压调整的方向错误,需要对“干扰”的方向进行改变。 ,Boost升压;光伏并网结构;Simulink建模;MPPT最大功率点追踪;扰动观察法;功率反馈;电压调整方向。,光伏并网结构中Boost升压MPPT控制策略的Simulink建模与功率反馈扰动观察法
STM32F103C8T6 USB寄存器开发详解(12)-键盘设备
科技活动人员数专指直接从事科技活动以及专门从事科技活动管理和为科技活动提供直接服务的人员数量
Matlab Simulink仿真探究Flyback反激式开关电源性能表现与优化策略,Matlab Simulink仿真探究Flyback反激式开关电源的工作机制,Matlab Simulimk仿真,Flyback反激式开关电源仿真 ,Matlab; Simulink仿真; Flyback反激式; 开关电源仿真,Matlab Simulink在Flyback反激式开关电源仿真中的应用
基于Comsol的埋地电缆电磁加热计算模型:深度解析温度场与电磁场分布学习资料与服务,COMSOL埋地电缆电磁加热计算模型:温度场与电磁场分布的解析与学习资源,comsol 埋地电缆电磁加热计算模型,可以得到埋地电缆温度场及电磁场分布,提供学习资料和服务, ,comsol;埋地电缆电磁加热计算模型;温度场分布;电磁场分布;学习资料;服务,Comsol埋地电缆电磁加热模型:温度场与电磁场分布学习资料及服务
1、文件内容:ibus-table-chinese-yong-1.4.6-3.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/ibus-table-chinese-yong-1.4.6-3.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊
基于51单片机protues仿真的汽车智能灯光控制系统设计(仿真图、源代码) 一、设计项目 根据本次设计的要求,设计出一款基于51单片机的自动切换远近光灯的设计。 技术条件与说明: 1. 设计硬件部分,中央处理器采用了STC89C51RC单片机; 2. 使用两个灯珠代表远近光灯,感光部分采用了光敏电阻,因为光敏电阻输出的是电压模拟信号,单片机不能直接处理模拟信号,所以经过ADC0832进行转化成数字信号; 3. 显示部分采用了LCD1602液晶,还增加按键部分电路,可以选择手自动切换远近光灯; 4. 用超声模块进行检测距离;
altermanager的企业微信告警服务
MyAgent测试版本在线下载
Comsol技术:可调BIC应用的二氧化钒VO2材料探索,Comsol模拟二氧化钒VO2的可调BIC特性研究,Comsol二氧化钒VO2可调BIC。 ,Comsol; 二氧化钒VO2; 可调BIC,Comsol二氧化钒VO2材料:可调BIC技术的关键应用
C++学生成绩管理系统源码
基于Matlab与Cplex的激励型需求响应模式:负荷转移与电价响应的差异化目标函数解析,基于Matlab与CPLEX的激励型需求响应负荷转移策略探索,激励型需求响应 matlab +cplex 激励型需求响应采用激励型需求响应方式对负荷进行转移,和电价响应模式不同,具体的目标函数如下 ,激励型需求响应; matlab + cplex; 负荷转移; 目标函数。,Matlab与Cplex结合的激励型需求响应模型及其负荷转移策略
scratch介绍(scratch说明).zip
内容概要:本文全面介绍了深度学习模型的概念、工作机制和发展历程,详细探讨了神经网络的构建和训练过程,包括反向传播算法和梯度下降方法。文中还列举了深度学习在图像识别、自然语言处理、医疗和金融等多个领域的应用实例,并讨论了当前面临的挑战,如数据依赖、计算资源需求、可解释性和对抗攻击等问题。最后,文章展望了未来的发展趋势,如与量子计算和区块链的融合,以及在更多领域的应用前景。 适合人群:对该领域有兴趣的技术人员、研究人员和学者,尤其适合那些希望深入了解深度学习原理和技术细节的读者。 使用场景及目标:①理解深度学习模型的基本原理和结构;②了解深度学习模型的具体应用案例;③掌握应对当前技术挑战的方向。 阅读建议:文章内容详尽丰富,读者应在阅读过程中注意理解各个关键技术的概念和原理,尤其是神经网络的构成及训练过程。同时也建议对比不同模型的特点及其在具体应用中的表现。
该文档提供了一个关于供应链管理系统开发的详细指南,重点介绍了项目安排、技术实现和框架搭建的相关内容。 文档分为以下几个关键部分: 项目安排:主要步骤包括搭建框架(1天),基础数据模块和权限管理(4天),以及应收应付和销售管理(5天)。 供应链概念:供应链系统的核心流程是通过采购商品放入仓库,并在销售时从仓库提取商品,涉及三个主要订单:采购订单、销售订单和调拨订单。 大数据的应用:介绍了数据挖掘、ETL(数据抽取)和BI(商业智能)在供应链管理中的应用。 技术实现:讲述了DAO(数据访问对象)的重用、服务层的重用、以及前端JS的继承机制、jQuery插件开发等技术细节。 系统框架搭建:包括Maven环境的配置、Web工程的创建、持久化类和映射文件的编写,以及Spring配置文件的实现。 DAO的需求和功能:供应链管理系统的各个模块都涉及分页查询、条件查询、删除、增加、修改操作等需求。 泛型的应用:通过示例说明了在Java语言中如何使用泛型来实现模块化和可扩展性。 文档非常技术导向,适合开发人员参考,用于构建供应链管理系统的架构和功能模块。
这份长达104页的手册由清华大学新闻与传播学院新媒体研究中心元宇宙文化实验室的余梦珑博士后及其团队精心编撰,内容详尽,覆盖了从基础概念、技术原理到实战案例的全方位指导。它不仅适合初学者快速了解DeepSeek的基本操作,也为有经验的用户提供了高级技巧和优化策略。
主题说明: 1、将mxtheme目录放置根目录 | 将mxpro目录放置template文件夹中 2、苹果cms后台-系统-网站参数配置-网站模板-选择mxpro 模板目录填写html 3、网站模板选择好之后一定要先访问前台,然后再进入后台设置 4、主题后台地址: MXTU MAX图图主题,/admin.php/admin/mxpro/mxproset admin.php改成你登录后台的xxx.php 5、首页幻灯片设置视频推荐9,自行后台设置 6、追剧周表在视频数据中,节目周期添加周一至周日自行添加,格式:一,二,三,四,五,六,日
运行GUI版本,可二开