DWR的基本原理以及前后台互相调用并整合SPRING的简易DEMO

    博客分类:
  • WEB技术
dwr
工作也已经有几年了, 最近突然心血来潮, 想写点技术博客,记录在工作和学习中碰到的一些问题,一方面方便自己以后查看,一方面也可以帮助下碰到同类问题的朋友们。 好了,闲话少说,进入第一篇博客的正文。
最近工作中有一个需求,需要开发一个类似QQ的即时聊天系统,不过要基于BS架构,上网搜索了下,JAVA中的COMET技术可以成为实现该需求的良好途径。
comet 【计】:基于 HTTP 长连接的“服务器推”技术,是一种新的 Web 应用架构。基于这种架构开发的应用中,服务器端会主动以异步的方式向客户端程序推送数据,而不需要客户端显式的发出请求。Comet 架构非常适合事件驱动的 Web 应用,以及对交互性和实时性要求很强的应用,如股票交易行情分析、聊天室和 Web 版在线游戏等。(百度百科)
现在网上有不少开源的comet框架,比如pushlet,dwr等, 当然, 你也可以自用用jquery甚至纯JS来实现。 我这里选用了dwr,毕竟是比较成熟的框架了,用起来可能可以比较顺手些。
简单介绍下DWR,DWR(Direct Web Remoting)是一个用于改善web页面与java类交互的远程服务器端Ajax开源框架,可以帮助开发人员开发包含AJAX技术的网站。它可以允许在浏览器里的代码使用运行在WEB服务器上的JAVA函数,就像它就在浏览器里一样。(百度百科)
显然,楼主不方便把实际工作的代码放上来,这里就放一个简易的DEMO, DEMO实现了一些基本功能:
1. 前台调用后台的JAVA方法,并利用JAVA返回值执行回调函数。
2. 在后台中将数据发送至第二个页面,并调用该页面的JS方法。
3. 与SPRING的简单整合。
下面楼主把实现这个工程的步骤重复下。
第一步, 自然要先导入jar包。 这个DEMO只需要DWR和SPRING2个jar包,如需要可以在附件中下载(包含在DEMO的项目中)。
然后,配置WEB.xml文件,配置如下,功能基本已经写了注释,再补充一点,通过[项目地址]/dwr可以查看被dwr转化的类,可以点击进入测试页面,这样对于一些不知道怎么在实际页面中调用的初学者,可以查看源文件复制其代码。 在实际项目发布后将其设置为false,以避免用户进入此页面。
Xml代码
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <web-appversion="2.4"xmlns="http://java.sun.com/xml/ns/j2ee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
  5. http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  6. servlet <!--dwr配置-->
  7. servlet-name>dwr-invoker</servlet-class org.directwebremoting.servlet.DwrServlet
  8. init-paramdescription>打开debug可以通过[项目地址]/dwr查看被加载的类param-name>debugparam-value>true>使用服务器推技术(反转AJAX)>activeReverseAjaxEnabled>使用comet方式推送数据>pollAndCometEnabledservlet-mappingurl-pattern>/dwr/*
  9. <!--Spring配置-->
  10. context-param>contextConfigLocation>/WEB-INF/classes/bean.xmllistenerlistener-class org.springframework.web.context.ContextLoaderListener
  11. web-app>

接下去是dwr的配置文件dwr.xml,将它放在web.xml的同一级即可。 这里是最简单的和spring的整合配置,如需更加复杂的功能,请自行搜索。
<!DOCTYPEdwrPUBLIC
  • "-//GetAheadLimited//DTDDirectWebRemoting1.0//EN"
  • "http://www.getahead.ltd.uk/dwr/dwr10.dtd"dwrallow<!--让dwr自动生成Controller.js文件-->
  • createcreator="spring"javascript="Controller"paramname="beanName"value="controller"/>
  • create<!--转化器,DWR对于自定义的BEAN需要转换,可以用*表示所有-->
  • convertmatch="songzl.message.User"converter="bean">

  • 下面spring的配置文件 bean.xml. 根据web.xml中的配置,将其放入src的根目录下。配置很简单,就是设置一个自动加载的bean的范围, 当然你也可以用<bean id="XXX" class="XXX"> 这样来加载。
    beansxmlns="http://www.springframework.org/schema/beans"
  • xmlns:context="http://www.springframework.org/schema/context"
  • xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  • http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd"
  • default-lazy-init="true"default-autowire="byName"<!--扫描songzl.message包下的类并将其自动加载为spring的bean-->
  • context:component-scanbase-package="songzl.message"context:component-scanbeans>

  • 接下去2个java类。 第一个user.java,一个放参数的javaben没什么可以多说
    Java代码
      packagesongzl.message;
    1. publicclassUser{
    2. privateStringname;
    3. privateStringpassword;
    4. publicStringgetName(){
    5. returnname;
    6. }
    7. voidsetName(Stringname){
    8. this.name=name;
    9. publicStringgetpassword(){
    10. returnpassword;
    11. voidsetPassword(Stringpassword){
    12. this.password=password;
    13. }

    第二个是控制类,Controller.java,也就是后台业务逻辑的主要实现类。 这里需要说下的是ScriptSession。ScriptSession是由DWR创建的,它用于保持长连接以管理页面。在JAVA中通过ServerContextFactory.get().getScriptSessionsByPage 来获取指定页面的ScriptSession以调用该页面的JS方法。关于ScriptSession后文还有一些补充。
    importjava.util.Collection;
  • importorg.directwebremoting.ScriptBuffer;
  • importorg.directwebremoting.ScriptSession;
  • importorg.directwebremoting.ServerContextFactory;
  • importorg.springframework.stereotype.Component;
  • @Component
  • classController{
  • publicStringgetLoginUser(Useruser){
  • finalStringresult="name:"+user.getName()+"----password:"+user.getpassword();
  • System.out.println(result);
  • StringrecivePage="/DwrTest/message/reciver.jsp";//接收方的页面/项目名/页面
  • Collection<ScriptSession>scss=ServerContextFactory.get().getScriptSessionsByPage(recivePage);//获取所有指定页面
  • for(ScriptSessionss:scss){
  • ss.addScript(newScriptBuffer("reciverMes('"+result+"')"));//调用页面的JS方法
  • returnresult;
  • }

  • 接下去是发送页面,sender.jsp。 要注意不要忘记导入engine.js和Controller.js。 其中Controller.js是DWR根据你的配置文件自动帮你生成的。
    <%@pagelanguage="java"contentType="text/html;charset=UTF-8"
  • pageEncoding="UTF-8"%>
  • <!DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML4.01Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
  • <html>
  • <head>
  • <Metahttp-equiv="Content-Type"content="text/html;charset=UTF-8">
  • <title>数据发送页面</title>
  • <scripttype='text/javascript'src='/DwrTest/dwr/engine.js'></script>
  • <scripttype="text/javascript"src="/DwrTest/dwr/interface/Controller.js"></script>
  • <scripttype="text/javascript">
  • functionsubmitLogin(){
  • varname=document.getElementById("name").value;
  • varpassword=document.getElementById("password").value;
  • varobj={name:name,password:password};//obj需要在dwr.xml中配置conventer,字段名需要和class中的一致
  • //回调函数,返回JAVA方法中的返回值
  • Controller.getLoginUser(obj,function(data){
  • alert("返回的值是"+data);
  • })
  • </script>
  • </head>
  • <body>
  • 账号:<inputtype="text"id="name"/>
  • 密码:<inputtype="text"id="password"/>
  • <inputtype="submit"value="提交"onclick="submitLogin()"/>
  • </body>
  • </html>


  • 最后是接收的页面。 reciver.jsp。 要注意的是一定不要忘记加上onload="dwr.engine.setActiveReverseAjax(true)" 楼主一开始就是忘了这句。 结果怎么也调试不出来。 蛋疼呐
    <title>数据接受页面</title>
  • functionreciverMes(mes){
  • alert(mes);
  • <bodyonload="dwr.engine.setActiveReverseAjax(true)">
  • <fontsize='5'>当发送页面点击发送信息,本地可以立即接受到发来的消息</font>
  • </html>

  • 这样这个工程基本就定型了。 打开http://localhost:8080/DwrTest/message/sender.jsp和http://localhost:8080/DwrTest/message/reciver.jsp两个页面。 在第一个页面的输入框中随便填一点值,点击提交。 第一个页面会执行其回调函数。 第二个页面会执行controller中的方法。 (注意 为示区别 2个页面alert的值是不一样的)
    最后,对ScriptSession作一点补充。"当我们访问一个页面的时候,如果是第一次访问,就会创建一个新的HttpSession,之后再访问的时候,就会保持当前的Session,即使是刷新,也能保持当前的HttpSession。 但是,ScriptSession不同,第一次访问,会创建一个ScriptSession,但是,如果你刷新,就会创建一个新的ScriptSession". 通过这段描述不难发现,如果用户多次刷新页面,将产生无数个无用的ScriptSession,占了内存不说还会影响后来用户的链接。
    怎么解决呢?DWR3 提供了ScriptSessionManager 这个接口来管理ScriptSession。 大家可以写一个类 复写DefaultScriptSessionManager这个方法,在其中捕获无用的scriptSession,并调用scriptSession.invalidate()将其无效化。 然后在WEB.XML的DWR的servlet配置中加入下面的代码:
    org.directwebremoting.extend.ScriptSessionManager
  • 你的实现类(X.X.XXX)
  • >

  • 具体实现代码就不贴了,可以通过搜索引擎搜索下。 并不是很复杂。
    • DwrTest.rar(3.4 MB)

    DWR的基本原理以及前后台互相调用并整合SPRING的简易DEMO的更多相关文章

    1. ios – 为什么Apple建议在串行后台队列中调度OpenGL命令,这不可避免地会导致崩溃?

      他们suggest:WhenusingGCD,useadedicatedserialqueuetodispatchcommandstoOpenGLES;thiscanbeusedtoreplacetheconventionalmutexpattern.我不明白这个建议.我无法解决这种冲突:当应用程序的app委托收到-applicationWillResignActive调用时,它必须立即停止调用任

    2. ios – Swift Realm新手:一个简单的Realm对象及其初始化器的问题

      几周前我一直是Objective-C的开发人员,并且听说过Realm.另一方面,我一直希望一点一点地迁移到Swift,所以我创建了一个涉及RealmSwift的小项目.这是什么意思?如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

    3. ios – 如何检查应用程序何时从后台返回到前台,而不是来自推送通知?

      如何从图标中查看应用程序的打开时间?本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

    4. android – 获取用户在后台发送到服务器的每日步数的最佳方法

      我应该如何衡量每日步骤?我可以使用这个可以覆盖此函数的服务publicvoidonSensorChangedthisdoesn’因为我的服务可能被破坏,所以看起来很准确.要么我可以尝试使用Google健身,但我每次尝试获取数据时都需要用户连接mGoogleapiclient.connect()有人有这方面的经验吗?本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

    5. android – 尝试为GreenDAO运行DaoGenerator时出现NoClassDefFoundError

      我有一个Android项目,使用AndroidStudio2.3,它使用GreenDAO生成与sqlite数据库交互的类.DaoGenerator项目之前总是工作……

    6. JSON schema配置规范使用教程

      这篇文章主要为大家介绍了JSON schema配置规范使用教程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

    7. Vue2 Element Schema Form 配置式生成表单的实现

      本文主要介绍了Vue2 Element Schema Form 配置式生成表单的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    8. 利用Spring框架为自己的校园卡充值(推荐)

      这篇文章主要介绍了利用Spring框架为自己的校园卡充值,本次实验主要运用了Spring的控制反转(IOC)和依赖注入(DI)等知识,通过利用Spring框架编写Java程序,实现学生卡的单次充值,如需对学生卡进行多次充值,可将部分代码修改即可实现,需要的朋友可以参考下

    9. jsp dwr级联效果代码

      dwr实现级联代码

    10. 使用spring mvc+localResizeIMG实现HTML5端图片压缩上传的功能

      这篇文章主要介绍了使用spring mvc+localResizeIMG实现HTML5端图片压缩上传的功能,非常具有实用价值,需要的朋友可以参考下。

    随机推荐

    1. xe-ajax-mock 前端虚拟服务

      最新版本见Github,点击查看历史版本基于XEAjax扩展的Mock虚拟服务插件;对于前后端分离的开发模式,ajax+mock使前端不再依赖后端接口开发效率更高。CDN使用script方式安装,XEAjaxMock会定义为全局变量生产环境请使用xe-ajax-mock.min.js,更小的压缩版本,可以带来更快的速度体验。

    2. vue 使用 xe-ajax

      安装完成后自动挂载在vue实例this.$ajaxCDN安装使用script方式安装,VXEAjax会定义为全局变量生产环境请使用vxe-ajax.min.js,更小的压缩版本,可以带来更快的速度体验。cdnjs获取最新版本点击浏览已发布的所有npm包源码unpkg获取最新版本点击浏览已发布的所有npm包源码AMD安装require.js安装示例ES6Module安装通过Vue.use()来全局安装示例./Home.vue

    3. AJAX POST数据中文乱码解决

      前端使用encodeURI进行编码后台java.net.URLDecoder进行解码编解码工具

    4. Koa2框架利用CORS完成跨域ajax请求

      实现跨域ajax请求的方式有很多,其中一个是利用CORS,而这个方法关键是在服务器端进行配置。本文仅对能够完成正常跨域ajax响应的,最基本的配置进行说明。这样OPTIONS请求就能够通过了。至此为止,相当于仅仅完成了预检,还没发送真正的请求呢。

    5. form提交时,ajax上传文件并更新到&lt;input&gt;中的value字段

    6. ajax的cache作用

      filePath="+escape;},error:{alert;}});解决方案:1.加cache:false2.url加随机数正常代码:网上高人解读:cache的作用就是第一次请求完毕之后,如果再次去请求,可以直接从缓存里面读取而不是再到服务器端读取。

    7. 浅谈ajax上传文件属性contentType = false

      默认值为contentType="application/x-www-form-urlencoded".在默认情况下,内容编码类型满足大多数情况。在这里,我们主要谈谈contentType=false.在使用ajax上传文件时:在其中先封装了一个formData对象,然后使用post方法将文件传给服务器。说到这,我们发现在JQueryajax()方法中我们使contentType=false,这不是冲突了吗?这就是因为当我们在form标签中设置了enctype=“multipart/form-data”,

    8. 909422229_ajaxFileUpload上传文件

      ajaxFileUpload.js很多同名的,因为做出来一个很容易。我上github搜AjaxFileUpload出来很多类似js。ajaxFileUpload是一个异步上传文件的jQuery插件传一个不知道什么版本的上来,以后不用到处找了。语法:$.ajaxFileUploadoptions参数说明:1、url上传处理程序地址。2,fileElementId需要上传的文件域的ID,即的ID。3,secureuri是否启用安全提交,默认为false。4,dataType服务器返回的数据类型。6,error

    9. AJAX-Cache:一款好用的Ajax缓存插件

      原文链接AJAX-Cache是什么Ajax是前端开发必不可少的数据获取手段,在频繁的异步请求业务中,我们往往需要利用“缓存”提升界面响应速度,减少网络资源占用。AJAX-Cache是一款jQuery缓存插件,可以为$.ajax()方法扩展缓存功能。

    10. jsf – Ajax update/render在已渲染属性的组件上不起作用

      我试图ajax更新一个有条件渲染的组件。我可以确保#{user}实际上是可用的。这是怎么引起的,我该如何解决呢?必须始终在ajax可以重新呈现之前呈现组件。Ajax正在使用JavaScriptdocument.getElementById()来查找需要更新的组件。但是如果JSF没有将组件放在第一位,那么JavaScript找不到要更新的内容。解决方案是简单地引用总是渲染的父组件。

    返回
    顶部