`
dyccsxg
  • 浏览: 201718 次
  • 性别: Icon_minigender_1
  • 来自: 青岛
社区版块
存档分类

DWR学习笔记

 
阅读更多

1. 简介

DWR(Direct Web Remoting) 是一个 Java 开源框架,一方面可以根据 Java 代码生成相应的 JavaScript 代码供客户端调用,另一方面也可以直接在 Java 代码中调用 JavaScript 代码向客户端推送数据。
# Download URL
http://directwebremoting.org/dwr/downloads/index.html
https://dist.apache.org/repos/dist/release/commons/logging/binaries/
# Documentation URL
http://directwebremoting.org/dwr/documentation/index.html
# 依赖 jar
commons-logging-1.1.3.jar
dwr.jar

2. JavaScript 调用 Java

2.1 编写 Java 代码

package org.demo.dwr.bean;
/**
 * bean - User
 * @author  
 * @date    2013-11-20
 * @file    org.demo.dwr.bean.User.java
 */
public class User {
    private String id;
    private String name;
    private String email;
    
    /**
     * toString
     */
    public String toString() {
    	StringBuilder sb = new StringBuilder();
    	sb.append('{');
    	sb.append("id:" + id).append(", ");
    	sb.append("name:" + name).append(", ");
    	sb.append("email:" + email);
    	sb.append('}');
    	return sb.toString();
    }

	public String getId() {
		return id;
	}

	public String getName() {
		return name;
	}

	public String getEmail() {
		return email;
	}

	public void setId(String id) {
		this.id = id;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setEmail(String email) {
		this.email = email;
	}
}
package org.demo.dwr.web;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.demo.dwr.bean.User;
import org.directwebremoting.WebContext;
import org.directwebremoting.WebContextFactory;

/**
 * dwr - UserDwr
 * @author  
 * @date    2013-11-20
 * @file    org.demo.dwr.web.UserDwr.java
 */
public class UserDwr {

	private static UserDwr instance = new UserDwr();
	private Map<String, User> allUsers = new HashMap<String, User>();
	
	/**
	 * 当 dwr.xml 中 creator 的类型为 static 时, 需要调用此方法获取一个实例
	 * @return
	 */
	public static UserDwr getInstance() {
		return instance;
	}
	
	/**
	 * 增加用户
	 * @param user
	 * @return
	 */
	public String addUser(User user) {
		allUsers.put(user.getId(), user);
		return "success";
	}
	
	/**
	 * 根据 id 查询用户
	 * @param id
	 * @return
	 */
	public String getUser(String id) {
		User user = allUsers.get(id);
		if (user == null) {
			return "User not found - [id: " + id + "]";
		}
		return user.toString();
	}
	
	/**
	 * 需要访问 request, response, session 等HTTP Servlet对象时只需要在参数列表中声明一下即可
	 * @param param1
	 * @param req
	 * @param resp
	 * @param session
	 */
	public void showServletObjects(
			String param1, 
			HttpServletRequest req, HttpServletResponse resp, HttpSession session) {
		System.out.println("param1   = " + param1);
		System.out.println("request  = " + req);
		System.out.println("response = " + resp);
		System.out.println("session  = " + session);
		
		// 也可以通过下面这种方式获取HTTP Servlet对象
		WebContext ctx = WebContextFactory.get();
		System.out.println("request  = " + ctx.getHttpServletRequest());
	}
}
2.2 修改 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" 
  xmlns="http://java.sun.com/xml/ns/j2ee" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="
    http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	<display-name>DwrTest</display-name>
    
	<servlet>
		<servlet-name>dwr-invoker</servlet-name>
		<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>dwr-invoker</servlet-name>
		<url-pattern>/dwr/*</url-pattern>
	</servlet-mapping>
	
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>
2.3 编写 WEB-INF/dwr.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC
    "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN"
    "http://directwebremoting.org/schema/dwr30.dtd">
<dwr>
    
    <allow>
        <!-- 定义需要暴露给前台的 Java 类 -->
        <create creator="static" javascript="UserDwr">
            <param name="class" value="org.demo.dwr.web.UserDwr" />
        </create>
        
        <!-- 定义需要进行转换的 Java Bean -->
        <convert converter="bean" match="org.demo.dwr.bean.*" />
    </allow>
    
</dwr>
2.4 编写 index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>DWR - Test</title>

<!-- 引入与 DWR 相关的 js 文件 -->
<script src='dwr/engine.js'></script>
<script src='dwr/util.js'></script>
<script src='dwr/interface/UserDwr.js'></script>

</head>
<body>
  
  <div>
      <input type="button" value="addUser" onclick="addUser()" />
      <input type="button" value="getUser" onclick="getUser()" />
      <input type="button" value="showServletObjects" onclick="showServletObjects()" />
  </div>
  <div id="result"></div>
  
</body>
<script type="text/javascript">
/**
 * 增加用户
 */
function addUser() {
	var user = {
	    id : '100',
	    name : 'zhangsan',
	    email : 'zhangsan@163.com'
    };
	UserDwr.addUser(user, {
        callback: function(retVal) {
            document.getElementById('result').innerHTML += '<br/>' + retVal; 
        },
		timeout: 3000,
		errorHandler: function(errorMsg) { 
            alert('Error Msg : ' + errorMsg); 
        }
    });
}
/**
 * 查询用户
 */
function getUser() {
	UserDwr.getUser('100', {
        callback: function(retVal) {
            document.getElementById('result').innerHTML += '<br/>' + retVal; 
        },
        timeout: 3000,
        errorHandler: function(errorMsg) { 
            alert('Error Msg : ' + errorMsg); 
        }
    });
}
/**
 * 访问 HTTP Servlet 对象
 */
function showServletObjects() {
	UserDwr.showServletObjects('101');
}
</script>
</html>
2.5 测试

3. Java 调用 JavaScript
3.1 编写Java代码
package org.demo.dwr.web;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.directwebremoting.ScriptBuffer;
import org.directwebremoting.ScriptSession;
import org.directwebremoting.ServerContext;
import org.directwebremoting.ServerContextFactory;
import org.directwebremoting.WebContext;
import org.directwebremoting.WebContextFactory;
import org.directwebremoting.extend.ScriptSessionManager;

/**
 * dwr - ServerStatusDwr
 * @author  
 * @date    2013-11-20
 * @file    org.demo.dwr.web.ServerStatusDwr.java
 */
public class ServerStatusDwr implements Runnable {

	private static ServerStatusDwr instance = new ServerStatusDwr();
	
	public static ServerStatusDwr getInstance() {
		return instance;
	}
	
	public ServerStatusDwr() {
		ScheduledExecutorService threadPool = Executors.newSingleThreadScheduledExecutor();
		threadPool.scheduleWithFixedDelay(this, 10, 10, TimeUnit.SECONDS);
	}
	
	@Override
	public void run() {
		ServerContext ctx = ServerContextFactory.get();
		if (ctx == null) {
			return;
		}
		
		SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
		String currentTime = format.format(new Date());
		
		// 在非 DWR 线程中向前台推送数据
		ScriptBuffer script = new ScriptBuffer();
		script.appendCall("callback_refreshServerTime", currentTime);
		ScriptSessionManager manager = ctx.getContainer().getBean(ScriptSessionManager.class);
		Iterator<ScriptSession> it = manager.getAllScriptSessions().iterator();
		ScriptSession session = null;
		while (it.hasNext()) {
			session = it.next();
			session.addScript(script);
		}
	}
	
	public void refreshServerTime() {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String currentTime = format.format(new Date());
		
		// 在 DWR 线程中向前台推送数据
		ScriptBuffer script = new ScriptBuffer();
		script.appendCall("callback_refreshServerTime", currentTime);
		WebContext ctx = WebContextFactory.get();
		ScriptSession session = ctx.getScriptSession();
		session.addScript(script);
	}
	
	public String echo(String value) {
		return "echo " + value;
	}
}
# 修改 WEB-INF/dwr.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC
    "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN"
    "http://directwebremoting.org/schema/dwr30.dtd">
<dwr>
    
    <allow>
        <!-- 定义需要暴露给前台的 Java 类 -->
        <create creator="static" javascript="UserDwr">
            <param name="class" value="org.demo.dwr.web.UserDwr" />
        </create>
        <create creator="static" javascript="ServerStatusDwr">
            <param name="class" value="org.demo.dwr.web.ServerStatusDwr" />
            <include method="refreshServerTime"/>
            <include method="echo"/>
        </create>
        
        <!-- 定义需要进行转换的 Java Bean -->
        <convert converter="bean" match="org.demo.dwr.bean.*" />
    </allow>
    
</dwr>
# 编写 status.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>DWR - Test</title>

<!-- 引入与 DWR 相关的 js 文件 -->
<script src='dwr/engine.js'></script>
<script src='dwr/util.js'></script>
<script src='dwr/interface/ServerStatusDwr.js'></script>

</head>
<body>
  
  <input type="button" value="echo" onclick="echo()" />
  <input type="button" value="refresh" onclick="refreshServerTime()" />
  <div id="result"></div>
  
</body>
<script type="text/javascript">
// 采用主动模式时需要去掉下面的注释
// dwr.engine.setActiveReverseAjax(true);
// dwr.engine.setNotifyServerOnPageUnload(true);
function echo() {
    ServerStatusDwr.echo('HelloWorld', {
        async: false,
        callback: function(retVal) {
            document.getElementById('result').innerHTML += '<br/>' + retVal;
        }
    });
}
function refreshServerTime() {
    ServerStatusDwr.refreshServerTime();
}
function callback_refreshServerTime(retVal) {
    document.getElementById('result').innerHTML += '<br/>' + retVal;
}
</script>
</html>
3.2 被动模式
采用被动模式时,当服务端需要向客户端推送数据时,DWR会先将数据缓存起来,等下次有客户端请求过来时,再将需要推送的数据附加在这次请求的结果中,一起返回给客户端。
采用被动模式时,不需要做什么特殊配置,因为DWR默认就是被动模式。


3.3 主动模式
采用主动模式时,是由客户端主动发起请求从服务端获取需要推送的数据,而不是将这些数据附加在其他请求的结果中进行返回。

# 采用主动模式时需要在 web.xml 中加入参数 activeReverseAjaxEnabled
# 同时在页面中需要加入 dwr.engine.setActiveReverseAjax(true);
	<servlet>
		<servlet-name>dwr-invoker</servlet-name>
		<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
		<init-param>
		    <param-name>activeReverseAjaxEnabled</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>
<script type="text/javascript">
// 采用主动模式时需要去掉下面的注释
dwr.engine.setActiveReverseAjax(true);
dwr.engine.setNotifyServerOnPageUnload(true);
// ...
</script>
4. 同步异步
DWR默认是异步调用,如果要修改成同步调用,有以下两种方法可以选择:
# 修改全局配置,将所有方法的调用模式都修改成同步
dwr.engine.setAsync(false);
# 修改局部配置,将当前方法的调用模式修改成同步
Remote.method(params, {
    async: false,
    callback: function(retVal){
        // ... 
    }
});
5. 错误处理
DWR中的错误处理也有两种:全局配置和局部配置
# 全局配置
dwr.engine.setErrorHandler(function(errorMsg, exception) {
    var info = 'Error: ' + errorMsg 
             + ' - Details: ' + dwr.util.toDescriptiveString(exception, 2);
    alert(info);
});
# 局部配置
Remote.method(params, {
    callback: function(retVal) {
        // ... 
    },
    errorHandler: function(errorMsg, exception) {
        var info = 'Error: ' + errorMsg 
                 + ' - Details: ' + dwr.util.toDescriptiveString(exception, 2);
        alert(info);
    }
});
6. 压缩 js
如果需要将DWR自动生成的 js 文件进行压缩处理,只需要在 WEB-INF/lib 目录中加入yuicompressor-2.4.8.jar 即可
# Download URL
https://github.com/yui/yuicompressor/releases
7. DWR-Spring
7.1 依赖 jar
spring-aop-3.2.5.RELEASE.jar
spring-beans-3.2.5.RELEASE.jar
spring-context-3.2.5.RELEASE.jar
spring-core-3.2.5.RELEASE.jar
spring-expression-3.2.5.RELEASE.jar
spring-web-3.2.5.RELEASE.jar
# Download URL
http://repo.spring.io/simple/libs-release-local/org/springframework/spring/3.2.5.RELEASE/
7.2 修改 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" 
  xmlns="http://java.sun.com/xml/ns/j2ee" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="
    http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	<display-name>DwrTest</display-name>
    
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:beans.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
	<servlet>
		<servlet-name>dwr-invoker</servlet-name>
		<servlet-class>org.directwebremoting.spring.DwrSpringServlet</servlet-class>
		<init-param>
		    <param-name>activeReverseAjaxEnabled</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>
	
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>
7.3 编写 src/beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"
    xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.directwebremoting.org/schema/spring-dwr
       http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd" >
    
    <!-- 自动扫描需要暴露给前台的 Java 类 -->
    <!-- Allow DWR to scan the classpath, detect beans annotated with -->
    <!-- @RemoteProxy & @RemoteMethod and register the beans and Creator proxies for them. -->
    <dwr:annotation-scan base-package="org.demo.dwr.web" scanRemoteProxy="true"/>
    
    <!-- 自动扫描需要进行转换的 Java Bean -->
    <dwr:configuration>
        <dwr:convert type="bean" class="org.demo.dwr.bean.*" />
    </dwr:configuration>
    
</beans>
7.4 修改 Java 类
# 在需要暴露给前台的 Java 类上添加 @RemoteProxy 注解
# 在需要暴露给前台的 Java 方法上添加 @RemoteMethod 注解
package org.demo.dwr.web;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.demo.dwr.bean.User;
import org.directwebremoting.WebContext;
import org.directwebremoting.WebContextFactory;
import org.directwebremoting.annotations.RemoteMethod;
import org.directwebremoting.annotations.RemoteProxy;

/**
 * dwr - UserDwr
 * @author  
 * @date    2013-11-20
 * @file    org.demo.dwr.web.UserDwr.java
 */
@RemoteProxy
public class UserDwr {
    
	private Map<String, User> allUsers = new HashMap<String, User>();
	
	/**
	 * 增加用户
	 * @param user
	 * @return
	 */
	@RemoteMethod
	public String addUser(User user) {
		allUsers.put(user.getId(), user);
		return "success";
	}
	
	/**
	 * 根据 id 查询用户
	 * @param id
	 * @return
	 */
	@RemoteMethod
	public String getUser(String id) {
		User user = allUsers.get(id);
		if (user == null) {
			return "User not found - [id: " + id + "]";
		}
		return user.toString();
	}
	
	/**
	 * 需要访问 request, response, session 等HTTP Servlet对象时只需要在参数列表中声明一下即可
	 * @param param1
	 * @param req
	 * @param resp
	 * @param session
	 */
	@RemoteMethod
	public void showServletObjects(
			String param1, 
			HttpServletRequest req, HttpServletResponse resp, HttpSession session) {
		System.out.println("param1   = " + param1);
		System.out.println("request  = " + req);
		System.out.println("response = " + resp);
		System.out.println("session  = " + session);
		
		// 也可以通过下面这种方式获取HTTP Servlet对象
		WebContext ctx = WebContextFactory.get();
		System.out.println("request  = " + ctx.getHttpServletRequest());
	}
}
package org.demo.dwr.web;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.directwebremoting.ScriptBuffer;
import org.directwebremoting.ScriptSession;
import org.directwebremoting.ServerContext;
import org.directwebremoting.ServerContextFactory;
import org.directwebremoting.WebContext;
import org.directwebremoting.WebContextFactory;
import org.directwebremoting.annotations.RemoteMethod;
import org.directwebremoting.annotations.RemoteProxy;
import org.directwebremoting.extend.ScriptSessionManager;

/**
 * dwr - ServerStatusDwr
 * @author  
 * @date    2013-11-20
 * @file    org.demo.dwr.web.ServerStatusDwr.java
 */
@RemoteProxy
public class ServerStatusDwr implements Runnable {
	
	public ServerStatusDwr() {
		ScheduledExecutorService threadPool = Executors.newSingleThreadScheduledExecutor();
		threadPool.scheduleWithFixedDelay(this, 10, 10, TimeUnit.SECONDS);
	}
	
	@Override
	public void run() {
		ServerContext ctx = ServerContextFactory.get();
		if (ctx == null) {
			return;
		}
		
		SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
		String currentTime = format.format(new Date());
		
		// 在非 DWR 线程中向前台推送数据
		ScriptBuffer script = new ScriptBuffer();
		script.appendCall("callback_refreshServerTime", currentTime);
		ScriptSessionManager manager = ctx.getContainer().getBean(ScriptSessionManager.class);
		Iterator<ScriptSession> it = manager.getAllScriptSessions().iterator();
		ScriptSession session = null;
		while (it.hasNext()) {
			session = it.next();
			session.addScript(script);
		}
	}
	
	@RemoteMethod
	public void refreshServerTime() {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String currentTime = format.format(new Date());
		
		// 在 DWR 线程中向前台推送数据
		ScriptBuffer script = new ScriptBuffer();
		script.appendCall("callback_refreshServerTime", currentTime);
		WebContext ctx = WebContextFactory.get();
		ScriptSession session = ctx.getScriptSession();
		session.addScript(script);
	}
	
	@RemoteMethod
	public String echo(String value) {
		return "echo " + value;
	}
}
# DWR上传下载文件
http://directwebremoting.org/dwr-demo/simple/upload.html
http://directwebremoting.org/dwr-demo/simple/download.html
// END

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics