1、简介
DWR(Direct Web Remoting)是一个用于改善web页面与Java类交互的远程服务器端Ajax开源框架,可以帮助开发人员开发包含AJAX技术的网站。它可以允许在浏览器里的代码使用运行在WEB服务器上的JAVA函数,就像它就在浏览器里一样。
以上是摘自百度百科里面的定义。
它的最新版本DWR0.6添加许多特性如:支持Dom Trees的自动配置,支持Spring(JavaScript远程调用spring bean),更好浏览器支持,还支持一个可选的commons-logging日记操作.
DWR包含2个主要部分:
a、 一个运行在服务器端的Java Servlet,它处理请求并且向浏览器发回响应。
b、 运行在浏览器端的JavaScript,它发送请求而且还能动态更新网页。
2、工作原理
DWR工作原理是通过动态把Java类生成为Javascript。它的代码就像Ajax魔法一样,你感觉调用就像发生在浏览器端,但是实际上代码调用发生在服务器端,DWR负责数据的传递和转换。这种从Java到JavaScript的远程调用功能的方式使DWR用起来有种非常像RMI或者SOAP的常规RPC机制,而且DWR的优点在于不需要任何的网页浏览器插件就能运行在网页上。 Java从根本上讲是同步机制,然而AJAX却是异步的。所以你调用远程方法时,当数据已经从网络上返回的时候,你要提供有反调 (callback) 功能的DWR。
3、实例应用
下面通过一个简单的例子(用户注册)介绍一下dwr框架的搭建。我这里是使用maven进行构建的,关于maven的相关入门先前在上一篇博客中已经做过介绍了。如果暂时还不熟悉的可以先参考一下上篇博客的内容自己试着了解一下。如果不喜欢使用maven,也可以直接在eclipse中创建一个web项目,创建方式和普通web项目一样,关于dwr的jar包的下载可以直接去官网下载,下载地址如下:
dwr官网:
http://directwebremoting.org/dwr/downloads/index.html
在eclipse中使用maven工具构建项目:
http://www.jb51.cc/article/p-xkfpnnlj-ww.html
3.1、pom.xml文件的配置
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.feizi</groupId>
<artifactId>DwrDemo</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>DwrDemo Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- DWR的jar包 -->
<dependency>
<groupId>org.directwebremoting</groupId>
<artifactId>dwr</artifactId>
<version>2.0.3</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
</dependencies>
<build>
<finalName>DwrDemo</finalName>
</build>
</project>
3.2、web.xml文件的配置
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems,Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>scriptCompressed</param-name>
<param-value>false</param-value>
</init-param>
<!-- 是servlet的加载顺序 数字越小代表加载的优先级越高 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
</web-app>
3.3、相关的java类
3.3.1、用户实体类User.java
/** * @Description:扩展说明 * @Copyright: 2015 dreamtech.com.cn Inc. All right reserved * @Version: V6.0 */
package com.feizi.pojo;
import java.io.Serializable;
/** * 用户实体类 * @Author: feizi * @Date: 2015年10月1日 下午3:55:00 * @ModifyUser: feizi * @ModifyDate: 2015年10月1日 下午3:55:00 * @Version:V6.0 */
public class User implements Serializable {
/** * @Field: serialVersionUID:TODO */
private static final long serialVersionUID = -26619408898905443L;
// 登录id,主键唯一
private String id;
// 登录名
private String name;
// 密码
private String password;
// 邮箱
private String email;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
}
3.3.2、数据库访问层, UserDAO:实现User的数据库访问,这里仅仅作为一个演示之用。
/** * @Description:扩展说明 * @Copyright: 2015 dreamtech.com.cn Inc. All right reserved * @Version: V6.0 */
package com.feizi.dao;
import java.util.HashMap;
import java.util.Map;
import com.feizi.pojo.User;
import com.sun.org.apache.regexp.internal.recompile;
/** * 实现User的数据库访问,这里作为一个演示,编写测试代码 * @Author: feizi * @Date: 2015年10月1日 下午3:57:13 * @ModifyUser: feizi * @ModifyDate: 2015年10月1日 下午3:57:13 * @Version:V6.0 */
public class UserDao {
//存放保存的数据
private static Map<String,Object> dataMap = new HashMap<String,Object>();
/** * 保存用户,持久操作 * @Discription:扩展说明 * @param user * @return * @return boolean * @Author: feizi * @Date: 2015年10月1日 下午3:58:56 * @ModifyUser:feizi * @ModifyDate: 2015年10月1日 下午3:58:56 */
public boolean save(User user){
if(dataMap.containsKey(user.getId())){
return false;
}
System.out.println("下面开始保存用户");
System.out.println("id:"+user.getId());
System.out.println("password:"+user.getPassword());
System.out.println("name:"+user.getName());
System.out.println("email:"+user.getEmail());
dataMap.put(user.getId(),user);
System.out.println("用户保存结束");
return true;
}
/** * 根据用户id查找用户 * @Discription:扩展说明 * @param id * @return * @return User * @Author: feizi * @Date: 2015年10月1日 下午4:01:22 * @ModifyUser:feizi * @ModifyDate: 2015年10月1日 下午4:01:22 */
public User findUser(String id){
return (User) dataMap.get(id);
}
}
3.3.3、业务控制层,UserService:需要在dwr配置文件中进行注册,注册成dwr的组件,提供给javascript访问。
/** * @Description:扩展说明 * @Copyright: 2015 dreamtech.com.cn Inc. All right reserved * @Version: V6.0 */
package com.feizi.service;
import com.feizi.dao.UserDao;
import com.feizi.pojo.User;
/** * service业务类 * @Author: feizi * @Date: 2015年10月1日 下午4:02:49 * @ModifyUser: feizi * @ModifyDate: 2015年10月1日 下午4:02:49 * @Version:V6.0 */
public class UserService {
UserDao userDao = new UserDao();
public boolean save(User user) {
return userDao.save(user);
}
public User find(String id) {
return userDao.findUser(id);
}
}
项目的完整截图如下:
3.4、dwr.xml文件的配置
注意,需要在web.xml的同一目录下,创建dwr.xml,这里我们不用自己创建,可以直接将下载下来的dwr.jar包文件中的dwr.xml文件给拷贝出来,然后自己修改一下即可。主要就是将java代码中编写的service业务类在dwr中进行注册,使之成为dwr的一个组件供dwr调用。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://getahead.org/dwr/dwr20.dtd">
<dwr>
<allow>
<create creator="new" javascript="userService">
<param name="class" value="com.feizi.service.UserService"/>
</create>
<convert converter="bean" match="com.feizi.pojo.User"/>
</allow>
</dwr>
备注:这里我们把UserService配置到了dwr中,create元素中,creater=”new”表示每调用一次UserService时,需要new一个这样的类;javascript=”userService”,表示提供给前台页面调用的javascirpt文件是userService.js。
convert元素用于数据类型转换,即java类和javascript之间相互转换,因为和前台交换的是User对象,因此需要对此使用bean转换。
3.5、编写页面进行测试。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<Meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>DWR测试</title>
<script type="text/javascript" src="dwr/interface/userService.js"></script>
<script type="text/javascript" src="dwr/engine.js"></script>
<script type="text/javascript" src="dwr/util.js"></script>
<script type="text/javascript"> //回调函数 function saveFun(data){ if(data){ alert("注册成功!!"); }else{ alert("登录id已经存在!!"); } } /* 保存用户 */ function save(){ var userMap = {}; userMap.id = regForm.id.value; userMap.password = regForm.password.value; userMap.name = regForm.name.value; userMap.email = regForm.email.value; userService.save(userMap,saveFun); } //回调函数 function findFun(data){ if(data == null){ alert('无法找到用户:' + queryForm.id.value); return; } alert("找到用户,id:"+data.id+",npassword:"+data.password+",nname:"+data.name+",nemail:"+data.email); } /* 查询用户 */ function find(){ userService.find(queryForm.id.value,findFun); } </script>
</head>
<body>
<h2>用户注册</h2>
<hr>
<br>
<form name="regForm">
登录id:<input type="text" name="id"><br>
登录口令:<input type="password" name="password"><br>
登录姓名:<input type="text" name="name"><br>
电子邮箱:<input type="text" name="email"><br>
<input type="button" name="submitBtn" value="提交" onclick="save();"><br>
</form>
<br>
<br>
<h2>用户查询</h2>
<hr>
<br>
<form name="queryForm">
登录id:<input type="text" name="id"><br>
<input type="button" name="submitBtn" value="提交" onclick="find();"><br>
</form>
</body>
</html>
3.6、大家可能注意到了index.jsp这个页面头部总共引入了三个js文件,下面进行一个简单的介绍:
<script type="text/javascript" src="dwr/interface/userService.js"></script>
<script type="text/javascript" src="dwr/engine.js"></script>
<script type="text/javascript" src="dwr/util.js"></script>
其中,engine.js和util.js这两个js文件是由dwr直接提供封装的,用户可以不必关心,只需要导入到相应的页面中即可,关于这两个文件可以从下载的dwr.jar包中找到。(解压即可)
userService.js这个js我们可以不用自己编写,这个是我们编写的UserService类,经dwr反射后,自动生成的javascript代码,它和UserService.java是对应的,供用户调用,实际上我们就是通过这个js文件去调用服务器端的UserService类的。
<script type="text/javascript" src="dwr/interface/userService.js"></script>
这个里面的js命名userService.js对应于dwr.xml配置文件中的javascript(dwr的组件)中定义的userService,需要注意,dwr/interface/userService.js这个路径中的interface不能漏掉了,貌似也不能改成其他的,当然有些牛逼的大神能够修改框架的例外,显然这里没有必要。
engine.js和util.js的放置:
3.7、以上这些都配置完了之后我们需要测试一下来验证成功与否,我们启动一下项目,然后浏览器中输入项目地址http://localhost:8090/DwrDemo/。
到这里就已经结束了,最后我们总结一下整个dwr的开发流程。大致如下:
1.编写后台业务代码,该代码是和dwr无关的。
2.确认业务代码中哪些类、哪些方法是要由javascript直接访问的。
3.编写dwr组件,对步骤2的方法进行封装,也就是说与业务相关的类和方法需要在dwr中进行注册,生成dwr可以调用的组件。
4.配置dwr组件到dwr.xml文件中,如果有必要,配置convert,进行java和javascript类型互转。
5.通过反射机制,dwr将步骤4的类转换成javascript代码,提供给前台页面调用。(这一步是由dwr框架自动完成的,用户可以不必关心)
5.编写网页,调用步骤5的javascript中的相关方法(间接调用服务器端的相关类的方法),执行业务逻辑,将执行结果利用回调函数返回。
6.在回调函数中,得到执行结果后,可以继续编写业务逻辑的相关javascript代码。
ok。全部结束了,思路上可能还是有些混乱。慢慢进步!!
项目源码示例已打包上传至csdn,有需要的可以去下载看看,不过都是些简单的示例,博客中也已经全部贴出来了。
http://download.csdn.net/detail/hu1991die/9163663
原文参考:
http://www.cnblogs.com/cyjch/archive/2012/02/16/2353758.html