1.pom.xml配置
jar引入
<dependency>
<groupId>org.directwebremoting</groupId>
<artifactId>dwr</artifactId>
<version>3.0.M1</version>
</dependency>
2.web.xml配置
下图为默认配置,想起讲解见 http://blog.csdn.net/rogerjava/article/details/8233246
<!-- dwr3 -->
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>allowGetForSafariButMakeForgeryEasier</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>crossDomainSessionSecurity</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>allowScriptTagRemoting</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
3.applicationContext.xml配置
注册bean到spring容器中去
<bean id="categoryBean" class="com.wpao.shop.dwr.OperCategory"></bean>
4.dwr.xml配置
web-info下,如果目录不同,需修改web.xml文件;
<allow>标签中包括可以暴露给javascript访问的东西。
<create>标签中指定javascript中可以访问的java类,并定义DWR应当如何获得要进行远程的类的实例。javascript属性值为js中的引用名;
<param>标签指定要公开给javascript的java类名。name="beanName" value="categoryBean"指调用bean名称为categoryBean
<include>标签指定要公开给javascript的方法。不指定的话就公开所有方法。
<convert>完成POJO(Java对象)和JavaScript类型之间的相互转换,从而保证Ajax交互的正常通信;
本案例为①Bean转换器:利用getter、setter方法;若Java对象的属性没有设置getter、setter方法该属性是无法被转换的;
http://www.cnblogs.com/devan/p/5252258.html
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN" "http://getahead.org/dwr/dwr30.dtd">
<dwr>
<allow>
<create creator="spring" javascript="OperCategory">
<param name="beanName" value="categoryBean"/>
<include method="getCategoryByid" />
<include method="GetCategoryInfoByid" />
</create>
<convert match="com.wpao.shop.bean.CategoryBean" converter="bean"></convert>
</allow>
</dwr>
5.ftl页面中引用
案例中生成的jsp在webRoot下面 但若引用util.js,engine.js,beanName.js的jsp页面不在webRoot下面,则必须加上<%=request.getContextPath() %>/dwr/engine.js 这里的src="dwr/engine.js"中的dwr要与web.xml中的< url-pattern >/dwr/* </ url-pattern >相对应
src= "<%=request.getContextPath() %>/dwr/interface/beanName.js" 和<create creator="spring" javascript="OperCategory">中的相同
<#include "../include/part_top.ftl" /> <script language="javascript" type="text/javascript" src="js/question/zxwd.js"></script> <script language="javascript" type="text/javascript" src="dwr/engine.js"></script> <script language="javascript" type="text/javascript" src="dwr/interface/OperCategory.js"></script> <div class="main"> <div class="current">当前位置:<a href="${Constants.web_5p}">首页</a> > <a href="zxwdlist.html">在线问答</a></div> <div style="width:100%; overflow:hidden;"></div> <div class="main_content2"> <div class="shopstyle"> <ul class="shopname"> <li><a id="is0" href="javascript:mkuaitj('0');" class="select">所有栏目</a></li> </ul> <div id="three" style="background:#FFF;"> <ul class="question" id="iulshow"></ul> </div> </div> <script type="text/javascript"> showcategory("${cname}"); </script> </div> </div> </form> <#include "../include/bottom.ftl" />
6.js调用
var base = "/theuser/"; //点击模块提交表单(模块中的分类随后由showcategory赋值): function mkuaitj(mkid) { document.getElementById("icname").value = mkid; document.getElementById("idefault1").value = ""; //模块提交,分类清空; document.getElementById("isflag").value = "1"; document.getElementById("iform1").submit(); } function showcategory(mkid) { if(mkid != "") { OperCategory.GetCategoryInfoByid(mkid, { callback:function(datalist) { if(datalist != null) { var lishow1 = ""; var tnum = 0; for(var i=0;i<datalist.length;i++) { tnum = tnum + datalist[i].inum; lishow1 = lishow1 + "<li>·<a οnclick='fentj("+datalist[i].id+");' style='cursor:hand;' class='ahover'>"+datalist[i].name+"</a> ("+datalist[i].inum+")</li>"; } var lishow = "<li>·<a οnclick='fentj();' style='cursor:hand;' class='ahover'>全部问题</a> ("+tnum+")</li>"; lishow = lishow + lishow1; document.getElementById("iulshow").innerHTML=lishow; } } }); if(mkid != 0){ document.getElementById("is0").className = ''; for(var j=8;j<=12;j++) { document.getElementById("is"+j).className = ''; } } document.getElementById("is"+mkid).className = 'select'; } } function fentj(fid) { document.getElementById("idefault1").value = fid; document.getElementById("isflag").value = "1"; document.getElementById("iform1").submit(); }
7.java方法
public class OperCategory {
@Resource
private ICategoryService categoryService;
Logger logger = Logger.getLogger(this.getClass());
//根据父类ID获取子分类:
public List<CategoryBean> getCategoryByid(int pid) {
List<CategoryBean> categoryList = new ArrayList<CategoryBean>();
try {
categoryList = categoryService.getCategoryByid(pid);
}catch(Exception e) {
logger.error("***[theuser]在线问答,获取问答分类异常,e:"+e.toString());
}
return categoryList;
}
//获取子分类及信息条数:
public List<CategoryBean> GetCategoryInfoByid(int mkid) {
List<CategoryBean> categoryList = new ArrayList<CategoryBean>();
try {
categoryList = categoryService.GetCategoryInfoByid();
}catch(Exception e) {
logger.error("***[theuser]在线问答,获取问答获取子分类及信息条数异常,e:"+e.toString());
}
return categoryList;
}
}
8.bean对象
public class CategoryBean {
private int id ;//类别id
private String name;//类别名称
private int pid;//父id
private int inum;//信息数量;
private int mkid;
setter/getter;
}
9.原理
通过客户端的engine.js作为客户端的引擎和服务端的dwr.jar作为服务端的引擎,以RPC的方式来获取数据。
RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。
可简单认为是一种逆ajax方式
原理:DWR的实现原理是通过反射,将java翻译成javascript,然后利用回调机制,从而实现了javascript调用Java代码
10.优点,确定:
1.浏览器兼容:
2.json的封装
3.多种对象的转换(ssh对象转换)
4.可以写更少的JS代码,做更多的事情
缺点:
1.出错不容易找
2.dwr配置很复杂
2.json的封装
3.多种对象的转换(ssh对象转换)
4.可以写更少的JS代码,做更多的事情
缺点:
1.出错不容易找
2.dwr配置很复杂
11.面试问题:
1.比如A和B发消息,DWR是怎么知道A找的是B,而不是C
2.A在messageSend.jsp发送消息,B只有在messageAccept.jsp中才接收到消息,B在index.jsp界面是接收不到消息的
a登录后,将其信息写入scriptSession,并在消息界面进行DWR的初始化,把scriptSession加入ScriptSessionListener进行监听;b发送消息后,服务器端引擎dwr.jar将消息追加到对应的scriptSession中去;
服务器端引擎engine.js接收到对应的消息后,根据methodName进行过滤。
2.A在messageSend.jsp发送消息,B只有在messageAccept.jsp中才接收到消息,B在index.jsp界面是接收不到消息的
a登录后,将其信息写入scriptSession,并在消息界面进行DWR的初始化,把scriptSession加入ScriptSessionListener进行监听;b发送消息后,服务器端引擎dwr.jar将消息追加到对应的scriptSession中去;
服务器端引擎engine.js接收到对应的消息后,根据methodName进行过滤。