Dwr 是一个 Java 开源库,帮助你实现Ajax网站。
DWR它可以让你在浏览器中的Javascript代码调用Web服务器上的Java,就像在Java代码就在浏览器中一样。
DWR的宣传语是 “ Easy Ajax For Java”,但是它原本不止如此的。
Ajax有一个很大的缺陷就是“无法满足传统桌面系统的需求——服务器端需要向客户端主动发送消息”。
Dwr 主要包括两部分: 在服务器上运行的 Servlet 来处理请求并把结果返回浏览器。 运行在浏览器上的 Javascript,可以发送请求,并动态改变页面。
Dwr 会根据你的 Java 类动态的生成Javascript代码。这些代码的魔力是让你感觉整个Ajax调用都是在浏览器上发生的,但事实上是服务器执行了这些代码,DWR负责数据的传递和转换。
http://localhost:8080/SpringMVC/led/toLed.do?userId=1
dwr会自动生成engine.js、util.js、interface/MessagePusher.js等虚拟文件。
执行JavaScript代码:MessagePusher.onPageLoad(userId);
就会调用java类MessagePusher的方法onPageLoad,同时触发ScriptSession管理器。
MessagePusher push = new MessagePusher();
//第一个参数0,表示广播
push.sendMessage("0", "天气预报:"+RandomUtil.getRandomString(16));
匹配的ScriptSession添加到Browser.getTargetSessions()中,待后面调用
异步任务:
private ScriptBuffer script = new ScriptBuffer();
public void run() {
//对应页面调用的方法名称及参数
script.appendCall("showMessage", msg);
Collection<ScriptSession> sessions = Browser.getTargetSessions();
for (ScriptSession scriptSession : sessions) {
scriptSession.addScript(script);
}
}
就会调用scriptSession对应页面的javscript方法showMessage()。
1、第一次访问一个页面,就会创建一个新的HttpSession,之后再访问的时候,就会保持当前的Session,即使是刷新,也能保持当前的HttpSession。
2、ScriptSession不同,第一次访问,会创建一个ScriptSession,但是,如果你刷新,就会创建一个新的ScriptSession.
3、代码入侵问题
因为dwr.xml,使得前端可以直接访问java类里面的public方法,public变量。
所以累中的变量尽量不要是public。我们也可以通过下面的方式,限制方法的调用:
标签,也就是说外界访问的时候,这个类中所有方法只能访问这个test方法
<!-- 配置DWR -->
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
<init-param>
<param-name >org.directwebremoting.extend.ScriptSessionManager </param-name>
<param-value >com.bert.dwr.DWRScriptSessionManager </param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>activeReverseAjaxEnabled</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>initApplicationScopeCreatorsAtStartup</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>jsonRpcEnabled</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>jsonpEnabled</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
注意: (1)dwr核心servlet处理器:org.directwebremoting.servlet.DwrServlet
(2)DWRScriptSessionManager 是scriptSession管理器
(3)url-pattern需要跟前端页面定义dwr需要js的路径,保持一致
例如:
<!-- 路径从web.xml中配置,不需要引入真实的js,项目自动生成 -->
<!-- 路径对应web.xml中配置的url-pattern -->
<script type="text/javascript" src='<%=request.getContextPath() %>/dwr/engine.js'></script>
<script type="text/javascript" src='<%=request.getContextPath() %>/dwr/util.js'></script>
<script type="text/javascript" src='<%=request.getContextPath() %>/dwr/interface/MessagePusher.js'></script>
<?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>
<!-- javascript对应前台引入的interface/MessagePusher.js文件名称 -->
<create creator="new" javascript="MessagePusher">
<param name="class" value="com.bert.dwr.MessagePusher"/>
</create>
</allow>
</dwr>
package com.bert.dwr;
import java.util.Collection;
import org.directwebremoting.Browser;
import org.directwebremoting.ScriptBuffer;
import org.directwebremoting.ScriptSession;
import org.directwebremoting.ScriptSessionFilter;
import org.directwebremoting.WebContextFactory;
import org.springframework.util.StringUtils;
/**
* MessagePusher
*/
public class MessagePusher {
public void onPageLoad(String userId) {
if (!StringUtils.isEmpty(userId)){
ScriptSession scriptSession = WebContextFactory.get().getScriptSession();
scriptSession.setAttribute("userId", userId);
System.out.println("添加了一个scriptSession: "+userId);
}
}
public void sendMessage(final String userid, final String message) {
try {
final String id = userid;
final String msg = message;
Browser.withAllSessionsFiltered(new ScriptSessionFilter() {
//如果返回true,那将匹配的ScriptSession添加到Browser.getTargetSessions()中,待后面调用
public boolean match(ScriptSession session) {
String userId = (String) session.getAttribute("userId");
if (userId == null) {
return false;
} else if ("0".equalsIgnoreCase(id)) {
return true;
} else {
return userId.equalsIgnoreCase(id);
}
}
}, new Runnable() {
private ScriptBuffer script = new ScriptBuffer();
public void run() {
//对应页面调用的方法名称及参数
script.appendCall("showMessage", msg);
Collection<ScriptSession> sessions = Browser.getTargetSessions();
for (ScriptSession scriptSession : sessions) {
scriptSession.addScript(script);
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class DWRScriptSessionManager extends DefaultScriptSessionManager {
public DWRScriptSessionManager(){
//绑定一个ScriptSession增加销毁事件的监听器
this.addScriptSessionListener( new DWRScriptSessionListener());
System. out.println( "bind DWRScriptSessionListener");
}
}
/**
* DWR ScriptSession 监听器
* DWRScriptSessionListener
*/
public class DWRScriptSessionListener implements ScriptSessionListener{
//维护一个Map key为session的Id, value为ScriptSession对象
public static final Map<String, ScriptSession> scriptSessionMap = new HashMap<String, ScriptSession>();
/**
* ScriptSession创建事件
*/
public void sessionCreated(ScriptSessionEvent event) {
WebContext webContext = WebContextFactory. get();
HttpSession session = webContext.getSession();
ScriptSession scriptSession = event.getSession();
scriptSessionMap.put(session.getId(), scriptSession); //添加scriptSession
System. out.println( "session: " + session.getId() + " scriptSession: " + scriptSession.getId() + "is created!");
}
/**
* ScriptSession销毁事件
*/
public void sessionDestroyed(ScriptSessionEvent event) {
WebContext webContext = WebContextFactory. get();
HttpSession session = webContext.getSession();
ScriptSession scriptSession = scriptSessionMap.remove(session.getId()); //移除scriptSession
System. out.println( "session: " + session.getId() + " scriptSession: " + scriptSession.getId() + "is destroyed!");
}
/**
* 获取所有ScriptSession
*/
public static Collection<ScriptSession> getScriptSessions(){
return scriptSessionMap.values();
}
}
<script type="text/javascript">
var userId = '${param.userId}';
function init(){
if (userId || userId != ''){
dwr.engine.setActiveReverseAjax(true);
dwr.engine.setNotifyServerOnPageUnload(true);
MessagePusher.onPageLoad(userId);
}
}
//页面加载时调用init函数
window.onload = init;
//对应appendCall设置的方法名称
function showMessage(msg) {
$("#msg").val(msg);
}
</script>