DWR 整合

来源:互联网 发布:常见软件生命周期模型 编辑:程序博客网 时间:2024/05/14 00:21
4.1 DWR与Servlet
有2个Java类你一般需要用在DWR中,是webContext和WebContextFactory 在DWR 1.x 它们在uk.ltd.getahead.dwr 包, DWR 2.0+在org.directwebremoting包。这2个类给与你访问标准Http servlet对象的入口。这些对象是:
? HttpServletRequest
? HttpServletResponse
? HttpSession
? ServletContext
? ServletConfig
4.1.1 使用webContext的方法:

Java代码
import uk.ltd.getahead.dwr.WebContext;
import uk.ltd.getahead.dwr.WebContextFactory;
//
import uk.ltd.getahead.dwr.WebContext;
import uk.ltd.getahead.dwr.WebContextFactory;
// Java代码
WebContext ctx = WebContextFactory.get();
req = ctx.getHttpServletRequest();
WebContext ctx = WebContextFactory.get();
req = ctx.getHttpServletRequest(); 处理Http request和response做为只读是非常重要的。因为,当Http headers也许会通过,那么有些浏览器会忽略它们(比如IE忽略缓存参数)。任何尝试改变Http body将会导致DWR错误。 WebContext使用一个本地线程变量,所以你能使用以上的代码放在任何地方。
也可以看一下 DWR的Java文档 ,或者详细看一下 WebContext 。 WebContext代替了DWR1.1中的ExecutionContext。
4.1.2 方法选择
在没有写依赖于DWR的代码时,要能够访问Http servlet对象是可以做到的(比如HttpServletRequest, HttpServletResponse, HttpSession, ServletContext or ServletConfig)。DWR将自动填充它。 举个例子:

Java代码
public class Remote {
public void method(int param, ServletContext cx, String s) { ... }
}
public class Remote {
public void method(int param, ServletContext cx, String s) { ... }
} 然后你将可以从Javascript中通访问它尽管没有ServletContext参数:

Java代码
Remote.method(42, "test", callback);
Remote.method(42, "test", callback);
DWR将为你填充这个参数。
对这个方法这里有个小小的警告,你要保证你的没有把’callback function’作为第一个参数,而应该把它作为最后一个参数,或者作为元数据对象
4.2 DWR与Spring
4.2.1 让DWR和Spring一起工作的检查列表
1. 确认你用的是最新版的DWR。Spring创造器已经有了变化,所以你最好检查一下DWR的最新版本。
2. 确认你的Spring的Bean在DWR外面运行良好。
3. 配置DWR和Spring一起工作。 (看下面)
4. 查看演示页面: http://localhost:8080/[ YOUR-WEBAPP ]/dwr ,检查spring的Bean是否出现。
DWR对于Spring没有运行期依赖,所以如果你不使用Spring那么Spring的支持不会产生任何影响到。
4.2.2 Spring Creator
这个创造器会在spring beans.xml里查询beans,并且会使用Spring去创建它们。如果你已经使用Spring,这个创造器会非常有用。否则将完全没有任何用处。 要让DWR使用Spring创造器去创建和远程调用beans,要像如下所示:

Java代码
<allow>
...
<create creator="spring" javascript="Fred">

</create>
</allow>
<allow>
...
<create creator="spring" javascript="Fred">

</create>
</allow>
4.2.3 找到Spring配置文件
有3个方法可以找到Spring配置文件
1. ContextLoaderListener
最简单的用法使从Spring-MVC里使用

Java代码
org.springframework.web.context.ContextLoaderListener
org.springframework.web.context.ContextLoaderListener
你不必使用整个Spring-MVC去确认这个普遍的解决方案使多么好。只要再你的web.xml里配置:

Java代码
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/beans.xml</param-value> </context-param>
<listener>
<listener-class> org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/beans.xml</param-value> </context-param>
<listener>
<listener-class> org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
2. 使用location参数
如果你喜欢指定的beans.xml在你的dwr.xml文件中,那么你能使用location参数。你可以指定你希望数量的,必须有唯一的以”location”开头的命名。比如:location-1, location-2。这些locations是作为参数传到Spring的ClassPathXmlApplicationContext:

Java代码
<allow>
...
<create creator="spring" javascript="Fred">


</create>
</allow>
<allow>
...
<create creator="spring" javascript="Fred">


</create>
</allow>
3. 设置beenFactory目录
Spring创造器有一个静态的方法:setOverrideBeanFactory(BeanFactory),这个方法提供一个可编程的方式去覆盖任何BeanFactories。
4.2.4 使用Spring配置DWR
Bram Smeets写了一个有意思的blog,教你配置DWR使用beans.xml代替WEB-INF/web.xml。 我也对于如何在beans.xml中指定dwr.xml很感兴趣,尽管这看上去有些Spring传染病的感觉。
4.3 DWR与JSF
DWR包括两个JSF的扩展点,一个创造器和一个ServletFilter。
4.3.1 JSF Creator
DWR1.1中有一个体验版的JsfCreator。你可以在dwr.xml中这样使用:

Java代码
<allow>
...
<create creator="jsf" javascript="ScriptName">


</create>
...
</allow>
<allow>
...
<create creator="jsf" javascript="ScriptName">


</create>
...
</allow> 这将允许你通过DWR调用ManagedBean。
4.3.2 Servlet Filter
DWR/Faces 过滤器允许你不在JSF的生命周期里调用FacesContext中的Bean。 要使用JsfCreator,你应该把DWR/Faces过滤器加到web.xml中。

Java代码
<filter>
<filter-name>DwrFacesFilter</filter-name>
<filter-class> uk.ltd.getahead.dwr.servlet.FacesExtensionFilter </filter-class>
</filter>
<filter-mapping>
<filter-name>DwrFacesFilter</filter-name>
<url-pattern>/dwr/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>DwrFacesFilter</filter-name>
<filter-class> uk.ltd.getahead.dwr.servlet.FacesExtensionFilter </filter-class>
</filter>
<filter-mapping>
<filter-name>DwrFacesFilter</filter-name>
<url-pattern>/dwr/*</url-pattern>
</filter-mapping> 这两个需要放在web.xml中与其他的filter和filter-mapping放在一起。

4.4 DWR与Struts
DWR能够和任何框架结合。这个网站是个极端巧妙的证据,因为它把DWR使用在Drupal(PHP)。 DWR和Struts整合有2个层次。最基础的层次就是同时使用这两个框架,这是非常容易的,但是这样就不允许在DWR和Struts之间共享Action了。 DWR能构调用任何方法,所以你也能从调用一个Struts action,除非你不想那么做。ActionForm的内容是什么,当返回ActionForward时DWR怎么做? 一个比较好方法是重构你想调用的Action,提取出Action的逻辑。DWR和你的Action就可以同时调用相同的方法了。
4.4.1 Struts creator
DWR1.1增加了一个StrutsCreator。你可以在dwr.xml中这样使用:

Java代码
<allow>
...
<create creator="struts" javascript="ScriptName">

</create>
...
</allow>
<allow>
...
<create creator="struts" javascript="ScriptName">

</create>
...
</allow> 这样你就能从DWR调用FormBeans。
4.4.2 开始顺序
如果正在使用Struts创造器,那么你应该确保Struts初始化在DWR之前。你要保证你在web.xml里有一个<load-on-startup>的值,其中Struts的值比DWR设置地要低。

4.5 DWR与Weblogic或PageFlow
DWR中有一个创造器可以和Weblogic或者Beehive中的PageFlow一起工作。 PageFlow creator DWR1.1中加入了一个PageFlowCreator。你可以这样使用:

Java代码
<allow>
...
<create creator="pageflow" javascript="ScriptName"/>
...
</allow>
<allow>
...
<create creator="pageflow" javascript="ScriptName"/>
...
</allow> 4.6 DWR与Hibernate
4.6.1 让DWR和Hibernate一起工作的检查列表
1. 确保你使用的是最新的DWR。Hibernate转换器是新东西,所以你需要下载最新版本
2. 确保你的Hiberante在没有DWR的时候工作正常。
3. 如果是Spring和Hibernate一起使用,那么你最好先了解一下如何将整合Spring。
4. 配置DWR,使之与Hibernate一起工作。 (看下面)。
5. 查看演示页面:http://localhost:8080/YOUR-WEBAPP/dwr,确定Spring的Bean可以出现。
4.6.2 HibernateBeanConverter
除了我们可以决定是否要使用lazy loaded属性,这个转换器非常类似于标准的BeanConverter。 在DWR1.1 Hibernate转换器被称为“hibernate”并且作用在hibernate2, 在DWR2.x有2个转换器被称为“hibernate2”并且作用在hibernate3。 使用HibernateBeanConverter也许有点风险,原因如下:
? 结构:HibernateBeanConverter不符合MVC模式,所以不能把对象在数据曾和表现曾之间进行隔离。这个风险可以通过在上面加上独立的bean来减轻。
? 性能: DWR试图通过相同的序列化方式来转换所有可以得到的属性(除了DWR仅仅读JavaBean属性的时候)。所以可能会出现通过HTTP序列化了你的整个数据的情况。通常这并不是你想要的。要减少这一风险可以使用BeanConverter(HibernateBeanConverter衍生于它)的排除某些属性的功能,如下所示:

Java代码


HibernateBeanConverter会尝试不去读取没有初始化的属性。如果你只是想读取所有的东西那么应该使用BeanConverter。 建议使用Hibernate3,实际上Hibernate2的情况,你会发现你得到的都是空的Bean。
4.6.3 Session管理
如果你使用Hibernate对象,你需要知道每一个DWR请求都是一个新的Servlet请求,所以你需要保证为每个请求打开一个Hiberante的Session。
如果你用Spring,那么可以很方便的使用Spring里面的OpenSessionInViewFilter,它可以保证为每个请求打开一个Hiberante的Session。类似的解决方案在其它Framework中也存在。


4.7 DWR与WebWork
WebWork支持在DWR2.0m3以后才有。 要可以通过DWR调用WW的Action,要做两件事。
4.7.1 配置dwr.xml
你必须在dwr的配置文件中加入这样的配置:

Java代码
<create creator="none" javascript="DWRAction">

<include method="execute" />
</create>
<convert converter="bean" match="org.directwebremoting.webwork.ActionDefinition">

</convert>
<convert converter="bean" match="org.directwebremoting.webwork.AjaxResult" />
<create creator="none" javascript="DWRAction">

<include method="execute" />
</create>
<convert converter="bean" match="org.directwebremoting.webwork.ActionDefinition">

</convert>
<convert converter="bean" match="org.directwebremoting.webwork.AjaxResult" /> 这样你AjaxWebWork Action调用返回一个action实例(而不是文字)。然后你必须包括action对象的转换器定义(package级别或单独action)。

Java代码
<convert converter="bean" match="your_action_package.*"/>
<convert converter="bean" match="your_action_package.*"/> 4.7.2 在JSP中导入脚本
下面这些代码开启DWR调用Action的功能。你还要导入DWRActionUtil.js脚本(在你的web脚本路径中) 像这样在JS中调用Action:

Java代码
DWRActionUtil.execute(id, params, callback, [displayMessage]);
DWRActionUtil.execute(id, params, callback, [displayMessage]); 1. id 参数
? actionUri: 要调用action的URI(没有 .action). 例如:

Java代码
DWRActionUtil.execute('/ajax/TestFM', 'myform', 'doOnTextResult');
DWRActionUtil.execute('/ajax/TestFM', 'myform', 'doOnTextResult');

? actionDefinitionObject: 在xwork.xml中定义的action对象. 必须指定下面的内容:
? namespace: xwork.xml中action的名称空间
? action: xwork.xml中action的名字
? executeResult: true|false (是否执行action的结果, 如果false直接返回action实例)
例如:

Java代码
DWRActionUtil.execute({
namespace:'/ajax',
action:'TestJS',
executeResult:'true'
}, 'data', doOnJSResult, "stream...");
DWRActionUtil.execute({
namespace:'/ajax',
action:'TestJS',
executeResult:'true'
}, 'data', doOnJSResult, "stream..."); 2. params 参数
? emptyParams: 传递{}忽略任何参数。例子:

Java代码
DWRActionUtil.execute('/ajax/TestFM', {}, doOnJSResult, "stream...");
DWRActionUtil.execute('/ajax/TestFM', {}, doOnJSResult, "stream...");
? fieldId: 被转换为action调用参数的字段的id。
例子:

Java代码
<input id="mytext" name="mytext" value="some value" type="text"/>
DWRActionUtil.execute('/ajax/TestFM', 'mytext', doOnJSResult, "stream...");
<input id="mytext" name="mytext" value="some value" type="text"/>
DWRActionUtil.execute('/ajax/TestFM', 'mytext', doOnJSResult, "stream...");
? formId: 表单的id. 所有的input值被转换为action调用参数。
Note : 如果你的action使用了parameter拦截器,那么你的action会得到正确的参数值,请参考WebWork的文档。
3. callback 参数
? callbackFunction: 在DWR中,这个函数在请求完毕后调用。
? callbackObject: 在DWR中,callback对象。
4. displayMessage参数
displayMessage 是可选参数,当请求完毕后显示的消息(参考DWR文档)
4.7.3 高级
你可以声明一个pre/post Action处理器,在web.xml中的一个context-wide初始化参数(dwrActionProcessor)。处理器必须实现org.directwebremoting.webwork.IDWRActionProcessor 接口。这个处理器将会在action之前和之后被调用,所以你可以做一些预处理或改变结果。
4.8 DWR与Acegi
整合DWR和Acegi是为了保护bean方法调用 在此之前有必须熟悉spring和acegi,我就不解释acegi的配置了,您可以从acegi网站下载最新版本。
4.8.1 问题提出
我们必须保护一个bean,通过DWR设置“exposed”。 Acegi是一个基于Spring的安全机制的框架,这个例子告诉你如何去阻止通过网页访问一个bean方法,如果它没有权限的。 在dwr.xml里,在没有acegi保护下,我们这样声明bean

Java代码
<create creator="spring" javascript="loanDWR" beanName="loanDWR">
<include method="addLoan" />
</create>
<create creator="spring" javascript="loanDWR" beanName="loanDWR">
<include method="addLoan" />
</create> 在Spring配置文件里,这个addLoan方法被网页调用,这个loadDWR bean是一个Spring管理的bean

Java代码
<bean id="loanDWR" class="fr.iremia.jlab.web.dwr.LoanDWR">
<property name="personDAO">
<ref bean="personDAO" />
</property>
<property name="loanDAO">
<ref bean="loanDAO" />
</property>
</bean>
<bean id="loanDWR" class="fr.iremia.jlab.web.dwr.LoanDWR">
<property name="personDAO">
<ref bean="personDAO" />
</property>
<property name="loanDAO">
<ref bean="loanDAO" />
</property>
</bean> 4.8.2 解决方案
然后我们怎么去阻止没有权限的访问loanDWR.addLoan这个方法呢?如下所示:
? 创建一个安全机制的拦截器

Java代码
<bean id="loanDWRSecurityInterceptor" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager" />
<property name="accessDecisionManager" ref="httpRequestAccessDecisionManager" />
<property name="objectDefinitionSource">
<value>fr.iremia.jlab.web.dwr.LoanDWR.addLoan=edit,admin
</value>
</property>
</bean>
<bean id="loanDWRSecurityInterceptor" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager" />
<property name="accessDecisionManager" ref="httpRequestAccessDecisionManager" />
<property name="objectDefinitionSource">
<value>fr.iremia.jlab.web.dwr.LoanDWR.addLoan=edit,admin
</value>
</property>
</bean> LoanDWR.addLoan方法,只能被管理员或者有修改角色权限的用户edit调用
想要了解acegi的属性:authenticationManager 和 httpRequestAccessDecisionManager,请参考http://acegisecurity.org/docbook/acegi.html
? 为bean创建一个代理
给原有的loanDWR Spring bean添加一个代理,使用Spring proxyfactorybean:

Java代码
<bean id="loanDWRSecure" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="loanDWR" />
<property name="interceptorNames">
<idref local="loanDWRSecurityInterceptor" />
</property>
</bean>
<bean id="loanDWRSecure" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="loanDWR" />
<property name="interceptorNames">
<idref local="loanDWRSecurityInterceptor" />
</property>
</bean> 现在,loadDWRSecure是个代理被loanDWR调用,每个调用addLoan方法将被Acegi拦截,只有拥有权限的用户才能调用
? 修改dwr配置文件
我们现在需要修改

Java代码
<create creator="spring" javascript="loanDWR" beanName="loanDWRSecure">
<include method="addLoan" />
</create> 
0 0