收藏 分销(赏)

【软件工程】DWR入门教程.docx

上传人:二*** 文档编号:4764146 上传时间:2024-10-12 格式:DOCX 页数:50 大小:82KB
下载 相关 举报
【软件工程】DWR入门教程.docx_第1页
第1页 / 共50页
本文档共50页,全文阅读请下载到手机保存,查看更方便
资源描述
如何开始用DWR 有两种方法开始DWR,简单的方式是下载WAR文件然后看看。但是这不能帮你知道如何轻松的把DWR整合到你的web应用中,所以还是推荐你按照下面的3个步骤做: 1. 安装DWR的Jar包 。把它放到你的webapp的WEB-INF/lib目录下。那里可能已经有很多其他的jar文件了。 2. 编辑配置文件 需要把下面的代码加到文件中。<servlet>那局部需要和其他的<servlet>在一起,<servlet-mapping>局部也一样。 <servlet> <servlet-name>dwr-invoker</servlet-name> <display-name>DWR Servlet</display-name> <servlet-class></servlet-class> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dwr-invoker</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping> 在WEB-INF目录下的web.xml旁边创立一个dwr.xml文件。可以从最简单的配置开始: <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN" " :// getahead.ltd.uk/dwr/dwr10.dtd"> <dwr> <allow> <create creator="new" javascript="JDate"> <param name="class" value="java.util.Date"/> </create> <create creator="new" javascript="Demo"> <param name="class" value="your.java.Bean"/> </create> </allow> </dwr> DWR配置文件定义了那些DWR会创立提供远程调用的Javascript类。在上面的例子中我们定义了两个类来提供远程调用,并为其提供的Javascript类的名字。 在上面我们使用了new创立器,它会调用没有参数的构造函数来创立实例,但是所有JavaBean必须有这一构造函数。还要注意DWR有一些限制: · 不要出现Javascript保存关键字;和保存关键字同名的函数指定被排除。多数Javascript的关键字和Java是相同的。所以你不可能有一个方法叫做"try()"。但是该死"delete()"对与Javascript有着特殊意义,而对Java那么不是。 · Javascript方法重载是不支持的,所以尽量不要再Java中使用。 3. 访问下面的URL ://localhost:8080/[YOUR-WEBAPP]/dwr/ 你可以看见一个页面,里面有第二步中的类。接着往里点,你会看到所有可以调用的方法列表。这个页面是动态生成用来测试的例子。 自己动手试一下! 怎么在你的web应用中使用 在文档中有很多例子演示如何动态更改页面中的文字、更新列表、操作表单,还有直接更改table中的内容。每一个都有如何实现的介绍。 另一种方式是看刚刚的页面中提供的代码: 到 ://localhost:8080/\[YOUR-WEBAPP\]/dwr/ 页面,点击你的类。查看源码,找到执行方法的那几行,把那些文字粘贴到你的HTML或JSP中。 要包括下面这些能产生神奇效果的Javascript文件的链接。 <script src='/[YOUR-WEBAPP]/dwr/interface/[YOUR-SCRIPT].js'></script> <script src='/[YOUR-WEBAPP]/dwr/engine.js'></script> 你也可以把其中/[YOUR-WEBAPP]/替换成你的web页面的相对路径。 DWR根据dwr.xml生成和Java代码类似的Javascript代码。 相对而言Java同步调用,创立与Java代码匹配的Ajax远程调用接口的最大挑战来至与实现Ajax的异步调用特性。 DWR通过引入回调函数来解决这个问题,当结果被返回时,DWR会调用这个函数。 有两种推荐的方式来使用DWR实现远程方法调用。可以通过把回调函数放在参数列表里,也可以把回调函数放到元数据对象里。 当然也可以把回调函数做为第一个参数,但是不建议使用这种方法。因为这种方法在处理自动处理 对象时(查看"Alternative Method")上会有问题。这个方法主要是为向下兼容而存在的。 简单的回调函数 假设你有一个这样的Java方法: public class Remote { public String getData(int index) { ... } } 我们可以在Javascript中这样使用: <script type="text/javascript" src="[WEBAPP]/dwr/interface/Remote.js"> </script> <script type="text/javascript" src="[WEBAPP]/dwr/engine.js"> </script> ... function handleGetData(str) { alert(str); } Remote.getData(42, handleGetData); 42是Java方法getData()的一个参数。 此外你也可以使用这种减缩格式: Remote.getData(42, function(str) { alert(str); }); 调用元数据对象(Meta-Data) 另外一种语法时使用"调用元数据对象"来指定回调函数和其他的选项。上面的例子可以写成这样: Remote.getData(42, { callback:function(str) { alert(str); } }); 这种方法有很多优点:易于阅读,更重要的指定额外的调用选项。 超时和错误处理 在回调函数的元数据中你可以指定超时和错误的处理方式。例如: Remote.getData(42, { callback:function(str) { alert(str); }, timeout:5000, errorHandler:function(message) { alert("Oops: " + message); } }); 查找回调函数 有些情况下我们很难区分各种回调选项(记住,Javascript是不支持函数重载的)。例如: Remote.method({ timeout:3 }, { errorHandler:somefunc }); 这两个参数之一是bean的参数,另一个是元数据对象,但是我们不能清楚的告诉DWR哪个是哪个。为了可以跨浏览器,我们假定null == undefined。 所以当前的情况,规那么是: · 如果第一个或最后一个是一个函数,那么它就是回调函数,没有元数据对象,并且其他参数都是Java的方法参数。 · 另外,如果最后一个参数是一个对象,这个对象中有一个callback成员,并且它是个函数,那么这个对象就是元数据对象,其他的都是Java方法参数。 · 另外,如果第一个参数是 null ,我们就假设没有回调函数,并且其他的都是Java方法参数。尽管如此,我们会检查最后一个参数是不是null,如果是就发出警告。 · 最后如果最后一个参数是null,那么就没有callback函数。 · 另外,发出错误信号是个糟糕的请求格式。 创造一个与Java对象匹配的Javascript对象 假设你有这样的Java方法: public class Remote { public void setPerson(Person p) { this.person = p; } } Person对象的结构是这样的: public Person { private String name; private int age; private Date[] appointments; // getters and setters ... } 那么你可以在Javascript中这样写: var p = { name:"Fred Bloggs", age:42, appointments:[ new Date(), new Date("1 Jan 2021") ] }; Remote.setPerson(p); 在Javascript没有出现的字段,在Java中就不会被设置。 因为setter都是返回'void',我们就不需要使用callback函数了。如果你想要一个返回void的效劳端方法的完整版,你也可以加上callback函数。很明显DWR不会向它传递任何参数。 TransformerFactoryConfigurationError 这个问题的现象是在启动有DWR的Web应用时出现如下stack trace: root cause javax.xml.transform.TransformerFactoryConfigurationError: Provider org.apache.xalan.processor.TransformerFactoryImpl not found javax.xml.transform.TransformerFactory.newInstance(Unknown Source) 这个问题和DWR没有什么关系,那是因为Tomcat没有配置好。比拟简单的解决方法是下载Xalan替换掉$TOMCAT-HOME/common/lib目录下的xalan.jar文件。DWR2.0能更好的处理这个问题,但是本质的问题还是因为DWR的XML序列化需要有XSLT解析器的支持。 如果你用JDK5还是有这个问题的话,你可以增加以下VM参数来使Tomcat正常工作。 -Djavax.xml.transform.TransformerFactory= com.sun.org. XML解析错误 在刚开始用DWR的时候经常遇到的一个错误就是XML解析错误。其实这和DWR没有多大关系,主要是因为Tomcat里面自带的Xerces的问题,要不是该有的时候没有,要不是不该有的时候有了。 · JDK 1.3自身没有XML解析器,所以你需要xercesImpl.jar和xml-apis.jar. · JDK 和 JDK 1.4.1 虽然有了XML解析器,但是有很多bug,所以你还是需要把xercesImpl.jar放到tomcat\common\endorsed目录下。 · JDK 和JDK 5自带的XML解析器工作的很好,你就不需要再加其他的了。 另外要提的一点是,不同版本的Tomcat需要的XML解析器不一样。所以要注意检查它和JDK的版本兼容性。 用BEA Weblogic的Classpath问题 Weblogic 8.1(有可能其他版本同样)可能找不到DWR的类。 这大多出现在dwr.jar放在APP-INF目录下(APP_INF/lib)的情况。在这种情况下DWR依然可以工作,例如debug页面可以看见,但是DWR找不到你的类。 解决方法是把dwr.jar放到WEB-INF/lib目录下。 没有cookies的情况下用DWR 当不能用cookies时,servlet标准通过URL重写来支持 Session。DWR 2.x通过它生成的URL来支持这项功能。但是DWR 1.x没有这个功能。你可以通过以下方法让DWR 1.x 也支持cookies: · 从dwr.jar中提取engine.js,保存到你的文件系统中,就像jsp文件一样. · 修改"DWREngine._sendData = function(batch)" 方法, 参加一行: statsInfo += ";jsessionid=" + <%="'"+session.getId()+"'"%> 这样就可以让DWR 1.x支持url重写了。DWR 2+默认支持。 传递额外的数据到callback函数 通常我们需要传递额外的数据到callback函数,但是因为所有的回调函数都只有一个参数(远程方法的返回结果),这就需要一些小技巧了。 解决方案就是使用Javascript的闭包特性。 例如,你的回调函数原本需要像这个样子: function callbackFunc(dataFromServer, dataFromBrowser) { // 用dataFromServer和dataFromBrowser做些事情...... } 那么你可以像这个组织你的函数: var dataFromBrowser = ...; // 定义一个闭包函数来存储dataFromBrowser的引用,并调用dataFromServer var callbackProxy = function(dataFromServer) { callbackFunc(dataFromServer, dataFromBrowser); }; var callMetaData = { callback:callbackProxy }; Remote.method(params, callMetaData); (调用元数据在脚本介绍中有解释) 换句话说,现在你作为callback函数传递过来的不是一个真正的callback,他只是一个做为代理的闭包,用来传递客户端的数据。 你可以用更简介的形式: var dataFromBrowser = ...; Remote.method(params, { callback:function(dataFromServer) { callbackFunc(dataFromServer, dataFromBrowser); } }); 效劳器性能优化 CPU瓶颈:经过严格的测试DWR的性能没什么问题。DWR上性能消耗同web效劳器和网络比起来可以忽略不计。如果你真的需要提升DWR的性能的话,可以把log级别设置ERROR或FATAL,但是主要还是要看你的编码情况。 Network瓶颈: DWR没有管理你的浏览器缓存的功能,所以它会不断的重复读取DWR的javascript文件。这里有一个简单的解决方法,把javascript文件复制到你的web-app中,这样web效劳器就可以更好的利用它了。你也可以考虑把所有的javascript文件合并成一个文件,然后用DOJO的压缩程序处理一个来节省流量。 我们可以做一个补丁,让DWR在web-app启动的时候用时间做为javascript文件的时间戳,但是这个并不十分重要,因为上面的补丁太简单了而且可以压缩合并Javascript文件。 WEB-INF/web.xml 参考手册 在web.xml中最简单的配置就是简单参加DWR的servlet,没有这个配置DWR就不会起作用: <servlet> <servlet-name>dwr-invoker</servlet-name> <servlet-class></servlet-class> </servlet> <servlet-mapping> <servlet-name>dwr-invoker</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping> 此外还可以参加一些重要和有用的参数。 Logging DWR可以工作在JDK1.3上,而JDK1.3不支持java.util.logging,但是我们想强迫任何人使用commons-logging或者log4j,所以当没有logging类的时候DWR就使用 Servlet.log()方法。尽管如此,如果DWR发现了commons-logging,就是使用它。 Commons-Logging 几乎每一个人都在使用commons-logging,因为大多数的servlet容器在使用它。所以如果你的web应用中没有明显的参加commons-logging包,它也会默认的配置好。 在这种情况下,logging是由或者log4j配置文件控制的。详细配置查看文档。 Servlet.log() 如果你用 Servlet.log(), 下面的配置控制logging: <init-param> <param-name>logLevel</param-name> <param-value>DEBUG</param-value> </init-param> 可用的值有:FATAL, ERROR, WARN (默认), INFO 和 DEBUG。 多个dwr.xml文件 和 J2EE平安 一般来说,你只需要一个dwr.xml文件,并且放置在默认的位置:WEB-INF/dwr.xml。 如果那样的话,你可以不用了解下面的配置。 有三个原因使你希望指定不同位置的dwr.xml文件。 · 你希望让dwr.xml文件和它能访问到的资源在一起。在这种情况下你需要一个这样的配置: <param-value>WEB-INF/classes/com/yourco/dwr/dwr.xml</param-value> 。 · 你有大量的远程调用类,希望把他们分成多个文件。在这种情况下你需要重复下面的配置几次,每一个中有不同的 param-name,并且以 &apos;config&apos; 开头。DWR会依次把他们都读进来。 · DWR可以使用Servlet标准的J2EE的URL平安机制来给不同的用户不同的访问权限。你只需要简单的定义多个dwr servlet,并且制定不同的名字,url和访问权限。 如果你希望使用这一功能,那么语法是这样的: <init-param> <param-name>config*****</param-name> <param-value></param-value> <description>What config file do we use?</description> </init-param> 在这里config*****意思是param-name要以字符串config开头。这个参数可以根据需要使用屡次,但是不能相同。 一个使用J2EE的平安机制的例子: <servlet> <servlet-name>dwr-user-invoker</servlet-name> <servlet-class></servlet-class> <init-param> <param-name>config-user</param-name> <param-value></param-value> </init-param> </servlet> <servlet> <servlet-name>dwr-admin-invoker</servlet-name> <servlet-class></servlet-class> <init-param> <param-name>config-admin</param-name> <param-value></param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dwr-admin-invoker</servlet-name> <url-pattern>/dwradmin/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>dwr-user-invoker</servlet-name> <url-pattern>/dwruser/*</url-pattern> </servlet-mapping> <security-constraint> <display-name>dwr-admin</display-name> <web-resource-collection> <web-resource-name>dwr-admin-collection</web-resource-name> <url-pattern>/dwradmin/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>admin</role-name> </auth-constraint> </security-constraint> <security-constraint> <display-name>dwr-user</display-name> <web-resource-collection> <web-resource-name>dwr-user-collection</web-resource-name> <url-pattern>/dwruser/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>user</role-name> </auth-constraint> </security-constraint> 使用插件(Plug-in) DWR里的很多部件都是可插入的,所以可以通过替换掉DWR的默认实现类来改变其功能。你可以在 <init-param> 中的 param-name 中指定你要替换的接口,并在 param-value 中指定自己的接口实现类。 可插入点是: · uk.ltd.getahead.dwr.AccessControl · uk.ltd.getahead.dwr.Configuration · uk.ltd.getahead.dwr.ConverterManager · uk.ltd.getahead.dwr.CreatorManager · uk.ltd.getahead.dwr.Processor · .getahead.dwr.ExecutionContext 这些可插入点默认的实现都在uk.ltd.getahead.dwr.impl中。 使用debug/test模式 你可以通过下面的参数让DWR进入debug/test模式: <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> 在debug模式里,DWR会为每一个远程调用类生成一个测试页面。这对于检查DWR是否工作和工作的怎么样是很有用的。这个模式还可以警告你一些存在的问题:javascript保存字问题,或者函数重载问题。 尽管如此,这个模式不应该使用在实际部署环境里面,因为它可以为攻击者提供你的效劳的大量信息。如果你的网站设计的好的话,这些信息不会帮助攻击者窥视你的网站内容,但是还是不要给任何人一个找到你错误的时机好。 DWR就是照上面的样子做的,没有任何保证,所以你的网站的平安是你的责任。请小心。 dwr.xml是DWR的配置文件。默认情况下,应该把它放到WEB-INF目录(web.xml的目录)下。 DTD DTD文档以及一个用DTDDoc生成的参考手册。 dwr.xml文件的结构如下: <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN" " :// getahead.ltd.uk/dwr/dwr10.dtd"> <dwr> <!-- init is only needed if you are extending DWR --> <init> <creator id="..." class="..."/> <converter id="..." class="..."/> </init> <!-- without allow, DWR isn't allowed to do anything --> <allow> <create creator="..." javascript="..."/> <convert converter="..." match="..."/> </allow> <!-- you may need to tell DWR about method signatures --> <signatures> ... </signatures> </dwr> 术语 这里是一些必须理解的术语 - 参数会被converted,远程Bean会被created。所以如果你有一个叫A的bean,它有一个方法叫A.blah(B) 那么你需要一个A的creator和一个B的converter。 <allow> allow段落里面定义的试DWR可以创立和转换的类。 Creators 我们要调用的每个类都需要一个<create ...>定义。creator有几种。比拟通用的是new关键字和Spring。更多的信息可以参见[Creaters]文档。 Converters 我们必须保证所有的参数都可以被转换。JDK中的多数类型已经有转换器了,但是你需要给DWR转换你的代码的权利。一般来说JavaBean的参数需要一个<convert ...>定义。 默认情况下,如下类型不需要定义就可以转换: · 所有的原生类型 boolean,int,double, 等等 · 原生类型的对象类型 Boolean,Integer,等等 · java.lang.String · java.util.Date 和SQL中的Date · 以上类型组成的数组 · 以上类型的集合类型 (Lists, Sets, Maps, Iterators, 等) · 从DOM, XOM, JDOM 和 DOM4J中的DOM对象 (类似 Element 和 Document) 要了解如何转换你的JavaBean或者其他类型的参数请查看Converters文档。 <init> 可选的init局部用来声明创造bean的类和转换bean的类。多数情况下你不需要用到他们。如果你需要定义一个新的Creator [JavaDoc] 和 Converter [JavaDoc] , 那么你就需要在这里定义他们。但是建议你现检查一下DWR是不是已经支持了。 在init局部里有了定义只是告诉DWR这些扩展类的存在,给出了如何使用的信息。这时他们还没有被使用。这中方式很像Java中的import语句。多数类需要在使用前先import一下,但是只有import语句并不说明这个类已经被使用了。每一个creator和converter都用id属性,以便后面使用。 <signatures> DWR使用反射来找出在转换时应该用那种类型。有时类型信息并不明确,这时你可以在这里写下方法的签名来明确类型。详细信息查看Signatures局部。 可以有多个dwr.xml文件(详细信息见)。每个文件中的定义会被加在一起。DWR用这个功能来加载根底配置文件。我们可以看看标准被配置文件来了解dwr.xml的内容。 转换器 转换器在客户端和效劳器之间转换数据. 下面这些转换器有单独章节介绍 · Array Converter · Bean and Object Converters · Collection Converter · Enum Converter · DOM Objects · Hibernate整合 · Servlet Objects ( ServletRequest, Session, etc) 根底的转换器 原生类型,String,像BigDecimal这样的简单对象的转换器已经有了。你不需要在dwr.xml中<allow>局部的<convert>中定义。它们默认支持。 Date转换器 Date转换器负责在Javascript的Date类型与Java中的Date类型(java.util.Date, java.sql.Date, java.sql.Times or java.sql.Timestamp)之间进行转换。同根底的转换器一样,DateConverter默认是支持的。 如果你有一个Javascript的字符串 (例如"01 Jan 2021") ,你想把它转换成Java的Date类型有两个方法:在javascript中用Date.parse()把它解析成Date类型,然后用DWR的DateConverter传递给效劳器;或者把它作为字符串传递给Server,再用Java中的SimpleDateFormat(或者类似的)来解析。 同样,如果你有个Java的Date类型并且希望在HTML使用它。你可以先用SimpleDateFormat把它转换成字符串再使用。也可以直接传Date给Javascript,然后用Javascript格式化。第一种方式简单一些,尽管浪费了你的转换器,而且这样做也会是浏览器上的显示逻辑受到限制。其实后面的方法更好,也有一些工具可以帮你,例如: · The Javascript Toolbox Date formatter · Web Developers Notes on Date formatting 其他对象 其实创立自己的转换器也很简单。Converter接口的Javadoc包含了信息。其实这种需要很少出现。在你写自己的Converter之前先看看BeanConverter,它有可能就是你要的。 The Creators – 创造器 dwr.xml文件中的create元素的结构如下: <allow> <create creator="..." javascript="..." scope="..."> <param name="..." value="..."/> <auth method="..." role="..."/> <exclude method="..."/> <include method="..."/> </create> ... </allow> 这里的多数元素都是可选的 - 你真正必须知道的是指定一个creator和一个javascript名字。 creator属性 是必须的 - 它用来指定使用那种创造器。 默认情况下DWR1.1有8种创造器。它们是: · new: 用Java的new关键字创造对象。 · none: 它不创立对象,看下面的原因。 (v1.1+) · scripted: 通过BSF使用脚本语言创立对象,例如BeanShell或Groovy。 · spring: 通过Spring框架访问Bean。 · jsf: 使用JSF的Bean。 (v1.1+) · struts: 使用Struts的FormBean。 (v1.1+) · pageflow: 访问Beehive或Weblogic的PageFlow。 (v1.1+) 如果你需要写自己的创造器,你必须在init局部注册它。 javascript属性 用于指定浏览器中这个被创造出来的对象的名字。你不能使用Javascript的关键字。 scope属性 非常类似servlet标准中的scope。 它允许你指定这个bean在什么生命范围。选项有"application", "session", "request" 和"page"。这些值对于Servlet和JSP开发者来说应该相当熟悉了。 scope属性是可选的。默认是"page"。如果要使用"session"需要cookies。当前的DWR不支持ULR重写。 param元素 被用来指定创造器的其他参数,每种构造器各有不同。例如,"new"创造器需要知道要创立的对象类型是什么。每一个创造器的参数在各自的文档中能找到。请查看上面的链接。 include和exclude元素 允许创造器来限制类中方法的访问。一个创造器必须指定include列表或exclude列表之一。如果是include列表那么暗示默认的访问策略是"拒绝";如果是exclude列表那么暗示默认的访问策略是"允许"。 例如要拒绝防范除了setWibble()以外的所有方法,你应该把如下内容添加到dwr.xml中。 <create creator="new" javascript="Fred"> <param name="class" value="com.example.Fred"/> <include method="setWibble"/> </create> 对于参加到create元素中的类的所有方法都是默认可见的。 auth元素 允许你指定一个J2EE的角色作为将来的访问控制检查: <create creator="new" javascript="Fred"> <param name="class" value="com.example.Fred"/> <auth method="setWibble" role="admin"/> </create> 'none' 创造器 'none' 创造器不创立任何对象 - 它会假设你不需要创立对象。这有可能是对的,有两个原因。 你可能在使用的scope不是"page"(看上面),并在在前面已经把这个对象创立到这个scope中了,这时你就不需要再创立对象了。 还有一种情况是要调用的方法是静态的,这时也不需要创立对象。DWR会在调用创立器之前先检查一下这个方法是不是静态的。 对于上诉两种情况,你仍然需要class参数,用来告诉DWR它是在操作的对象类型是什么。 使用静态方法 DWR会在调用创立器之前先检查一下这个方法是不是静态的,如果是那么创造器不会被调用。很显然这个逻辑适用于所有
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传
相似文档                                   自信AI助手自信AI助手

当前位置:首页 > 通信科技 > 软件工程

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:4009-655-100  投诉/维权电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服