由于项目中最近需要用到dwr实现一些功能,因此在网上和dwr官网上找了一些资料进行学习。在此记录一下。(此处实现简单的dwr应用和dwr消息反向推送)
一、引入dwr的包
org.directwebremoting dwr 3.0.1-RELEASE
二、引入spring的包,因为示例代码中和spring进行了整合,spring的包略。
三、spring的配置文件(启用注解扫描即可)
四、修改web.xml
contextConfigLocation classpath:spring/applicationContext.xml org.springframework.web.context.ContextLoaderListener org.directwebremoting.servlet.DwrListener dwr-invoker DWR Servlet Direct Web Remoter Servlet org.directwebremoting.servlet.DwrServlet fileUploadMaxBytes 1024000 debug false accessLogLevel runtimeexception activeReverseAjaxEnabled true initApplicationScopeCreatorsAtStartup true jsonRpcEnabled true jsonpEnabled true preferDataUrlSchema false org.directwebremoting.extend.ScriptSessionManager com.huan.dwr.simple.reverseajax.DwrScriptSessionManager 1 dwr-invoker /dwr/*
注:1.测试环境中可以将debug的参数改为true,开发环境改为false
2.fileUploadMaxBytes 文件上传时限制上传文件的大小
3.org.directwebremoting.extendScriptSessionManager 为修改dwr默认的scriptSession的管理,默认情况下,页面上每刷新一次,都将会产生一次scriptsession,这样会产生没有的 scriptsession,浪费服务器的资源。而HttpSession只在用户第一次访问服务器时产生,所以可以考虑使用httpSession和 ScriptSession结合管理scriptsession.即需要重写dwr ScriptSessionManager接口中的方法
五、dwr的配置(默认会找web-inf 下的dwr.xml文件)
六、简单的dwr实例应用
1.jsp页面引入dwr需要的js文件
2.jsp页面的代码
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>测试dwr简单的功能
- 调用无参方法:
- 调用一个参数的方法:
- 调用多个参数的方法:
- 后台返回值到前台:
- 处理实体类的信息:
- 处理异常信息:
- 实现简单的文件上传:
2.后台对应的java代码
package com.huan.dwr.simple; import java.io.File; import java.io.IOException; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.directwebremoting.io.FileTransfer; import org.springframework.stereotype.Component; import com.huan.dwr.simple.data.Study; /** * 测试一下dwr调用简单的java方法 * * @描述 * @作者 huan * @时间 2016年4月11日 - 下午7:11:02 */ @Component("simpleDwrTest") public class SimpleDwrTest { /** * 调用无参数的构造方法 */ public void noArgumentMethod() { System.out.println("invoked..."); } /** * 调用一个参数的方法 * * @param hello */ public void hellowArgument(String hello) { System.out.println(hello + " world."); } /** 调用多个参数的方法 */ public void invokedMoreArgument(String param1, String param2) { System.out.println(String.format("这是接收到的参数:[%s]-[%s]", param1, param2)); } /** * 后台返回值到前台 * * @param value * @return */ public String returnValue(String value) { return "后台返回的值:" + value; } /** * 处理错误信息 */ public void handleError() { System.out.println("该方法将会抛出异常"); throw new RuntimeException("后台出异常了."); } /** * 以实体类作为参数 * @param study * @return */ public String addStudy(Study study) { System.out.println(study); return "添加学生成功!!!"; } /** * 文件上传 * * @param fileName * @param flie * @return * @throws IOException */ public String fileUpload(String msg,FileTransfer fileTransfer) throws IOException { try { System.out.println(fileTransfer.getFilename()); System.out.println(fileTransfer.getMimeType()); System.out.println(fileTransfer.getSize()); System.out.println(fileTransfer.getOutputStreamLoader()); FileUtils.copyInputStreamToFile(fileTransfer.getInputStream(), new File("D:" + File.separator + fileTransfer.getFilename())); } catch (IOException e) { e.printStackTrace(); } finally { IOUtils.closeQuietly(fileTransfer.getInputStream()); } return "文件上传成功."; } }
可以看到,使用了dwr后,可以使访问后台,变得简单了。 比如文件的上传也变得简单了。
注意:文件的上传需要依赖 commons-fileupload-version.jar这个jar包。
在项目中有时需要用到后台发生了变化,需要及时通知到前台,这个可以使用dwr的来实现。
注意: 由 于scriptSession比较特殊,页面每次刷新都会创建一个scriptsession,这个不符合我们的需求,应当只需要一个 scriptSession即可。然后我们知道httpsession是第一次访问服务器时创建的,并且在整个应用中只有一个,所以可以使用 httpsession的结合scriptsession做一些事情。
在dwr3中提供了ScriptSessionListener用于 监听scriptsession的创建和销毁。因此,我们创建一个类实现ScriptSessionListener接口,在这个类中维护一个 map,map的key为httpsession的id,值为Scriptsession.
步骤:
一、写一个类实现ScriptSessionListener接口,在此接口中实现自己维护scriptsession
public class HandleScriptSessionLinstener implements ScriptSessionListener { private static final ConcurrentHashMapSCRIPT_SESSIONS = new ConcurrentHashMap (); /** * ScriptSession 创建时触发 */ @Override public void sessionCreated(ScriptSessionEvent ev) { String sessionId = WebContextFactory.get().getSession().getId(); SCRIPT_SESSIONS.put(sessionId, ev.getSession()); } /** * ScriptSession销毁时触发 */ @Override public void sessionDestroyed(ScriptSessionEvent ev) { SCRIPT_SESSIONS.remove(WebContextFactory.get().getSession().getId()); } /** 获取所有的scriptsession */ public static Collection getAllSctiptSessions() { return SCRIPT_SESSIONS.values(); } }
二、写一个类继承默认的scriptsession管理器DefaultScriptSessionManager,在构造方法中注入上一步自己写的scriptsessionlistener,然后重写获取scriptsession的方法
public class DwrScriptSessionManager extends DefaultScriptSessionManager { /** * 注入自己的scriptsession管理 */ public DwrScriptSessionManager() { this.addScriptSessionListener(new HandleScriptSessionLinstener()); } @Override public CollectiongetAllScriptSessions() { return HandleScriptSessionLinstener.getAllSctiptSessions(); } }
三、在web.xml配置文件中进行配置(DwrServlet参数中进行配置)
org.directwebremoting.extend.ScriptSessionManager com.huan.dwr.simple.reverseajax.DwrScriptSessionManager
四、写后台推送的业务逻辑,此处简单的实现为,每隔5秒中向前台推送一个数据
package com.huan.dwr.simple.reverseajax; import java.util.Random; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.directwebremoting.Browser; import org.directwebremoting.ScriptSession; import org.directwebremoting.ScriptSessionFilter; import org.directwebremoting.ScriptSessions; import org.directwebremoting.WebContext; import org.directwebremoting.WebContextFactory; import org.directwebremoting.extend.UninitializingBean; import org.springframework.stereotype.Component; /** * 推送消息到客户端 * * @描述 * @作者 huan * @时间 2016年4月11日 - 下午9:05:49 */ @Component("pushMessage2Client") public class PushMessage2Client implements Runnable, UninitializingBean { private ScheduledThreadPoolExecutor threadPool = null; /** 保存在scriptsession中的属性 */ private static final String LOGIN_NAME = "LOGIN_NAME"; private Random random = new Random(); public PushMessage2Client() { threadPool = new ScheduledThreadPoolExecutor(1); /** * 每隔5秒推送数据到前台客户端 */ threadPool.scheduleAtFixedRate(this, 1, 5, TimeUnit.SECONDS); } @Override public void run() { final int randomNumber = random.nextInt(5000); Browser.withAllSessionsFiltered(new ScriptSessionFilter() { @Override public boolean match(ScriptSession session) { System.out.println("登录名为:" + session.getAttribute(LOGIN_NAME)); return true; } }, new Runnable() { @Override public void run() { /** * 调用客户端的show方法,并将randomNumber作为参数 * 如果上方那个过滤器返回true:则此方法调用 * 返回false:则此方法不调用 */ ScriptSessions.addFunctionCall("show", randomNumber); } }); } /** 添加属性到scriptSession中 */ public void addScriptSessionAttribute(String loginName) { WebContext webContext = WebContextFactory.get(); ScriptSession scriptSession = webContext.getScriptSession(); scriptSession.setAttribute(LOGIN_NAME, loginName); } @Override public void destroy() { if (null != threadPool) { threadPool.shutdown(); } } }
五、前台jsp的写法:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>测试dwr简单的功能
到此,一个简单的dwr运用和dwr反向ajax消息推送就实现了,如有那些地方写错了,欢迎指出。