一、DWR簡介
dwr
是一個Ajax
框架,官方網站:http://directwebremoting.org/dwr/
,最新版本3.0.1
,要求jdk1.6
及以上。
如下圖所示,可以通過DWR來調用Java方法,並通過DWR封裝的工具類來對頁面元素進行簡單處理:
上面的展示是對Ajax的封裝,簡化了用戶的操作,當然最常用的還是逆向Ajax(需要DWR2.0
及以上版本),就是俗稱的服務器端推送:
逆向Ajax相對比較難一點,下面先展示js調用Java方法的例子。
二、DWR示例-js調用Java方法
2.1 創建Web項目
創建Web
項目,並將dwr-3.0.1-RELEASE.jar
和commons-logging-1.2.jar
放入WEB-INF/lib
下,dwr-3.0.1-RELEASE.jar
是DWR必須要的jar包,最新版本為3.0.1-RELEASE
,它依賴commons-logging-1.2.jar
日志包。最終項目結構如下:
若使用Maven,則Maven坐標如下:
<dependency> <groupId>org.directwebremoting</groupId> <artifactId>dwr</artifactId> <version>3.0.1-RELEASE</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency>
Maven創建Web項目查看(待續)。本項目使用jdk1.7,tomcat7搭建。
2.2 修改web.xml
DWR的js調用Java代碼,本質上還是通過Ajax來訪問,因此需要在web.xml
中配置DWR接收js請求的servlet,配置如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>testweb</display-name> <servlet> <servlet-name>dwr-invoker</servlet-name> <!-- 接收js的Ajax請求的servlet --> <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>dwr-invoker</servlet-name> <!-- 攔截指定的URL --> <url-pattern>/dwr/*</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
若使用的不是jdk1.7及Tomcat7注意修改web.xml的頭信息,為低版本。
2.3 創建被調用的Java類
創建一個普通的Java類即可,如下:
package yiwangzhibujian; import java.util.Date; /** * @author yiwangzhibujian */ @SuppressWarnings("deprecation") public class HelloWorld{ /** * 無參無返回值 */ public void helloNN(){ System.out.println(new Date().toLocaleString() + " js訪問helloNN方法"); } /** * 有參無返回值 */ public void helloYN(String name){ System.out.println(new Date().toLocaleString() + " js訪問helloYN方法,name=" + name); } /** * 無參有返回值 */ public String helloNY(){ System.out.println(new Date().toLocaleString() + " js訪問helloNY方法"); return "Hello World!"; } /** * 有參有返回值 */ public String helloYY(String name){ System.out.println(new Date().toLocaleString() + " js訪問helloYY方法,name=" + name); return "Hello " + name; } }
通過DWR調用Java方法使用普通的Java類即可,不需要訪問servlet。
2.4 創建DWR配置文件
在WEB-INF
根路徑下創建DWR的配置文件,dwr.xml
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN" "http://getahead.org/dwr/dwr30.dtd"> <dwr> <allow> <create creator="new" javascript="HelloWorld"> <param name="class" value="yiwangzhibujian.HelloWorld" /> </create> </allow> </dwr>
create=“new”
,即通過默認的構造方法使用new來創建對象,javascript="HelloWorld",HelloWorld表示調用類的名稱,即在js中Java對象的名字,<param>
即用來配置DWR訪問的類。簡單來說,value
就是js要調用的類,javascript
屬性即是為這個類起一個簡單的別名。
2.5 創建JSP頁面
本示例簡單的在index.jsp中編寫:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path=request.getContextPath(); String basePath=request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <script type='text/javascript' src='dwr/engine.js'></script> <script type='text/javascript' src='dwr/util.js'></script> <script type='text/javascript' src='dwr/interface/HelloWorld.js'></script> <style type="text/css"> td{ border: solid 1px; } </style> </head> <body> <table> <tr> <td>無參無返回值</td> <td colspan="3"><input type="button" value="helloNN" onclick="helloNN();"></td> </tr> <tr> <td>有參無返回值</td> <td colspan="2"><input type="text" id="helloYNName"></td> <td><input type="button" value="helloYN" onclick="helloYN();"></td> </tr> <tr> <td>無參有返回值</td> <td><input type="button" value="helloNY" onclick="helloNY();"></td> <td colspan="2"><input type="text" id="helloNYValue"></td> </tr> <tr> <td>有參有返回值</td> <td><input type="text" id="helloYYName"></td> <td><input type="button" value="helloYY" onclick="helloYY();"></td> <td><input type="text" id="helloYYValue"></td> </tr> </table> </body> <script type="text/javascript"> //無參無返回值 function helloNN(){ HelloWorld.helloNN(); } //有參無返回值 function helloYN(){ var name = dwr.util.getValue("helloYNName"); HelloWorld.helloYN(name); } //無參有返回值 function helloNY(){ HelloWorld.helloNY(function(data) { dwr.util.setValue("helloNYValue", data); }); } //有參有返回值 function helloYY(){ var name = dwr.util.getValue("helloYYName"); HelloWorld.helloYY(name, function(data) { dwr.util.setValue("helloYYValue", data); }); } </script> </html>
必須引入的兩個js,第二個js不是真實存在的js文件,而是項目啟動訪問后動態生成的js,這個js的名稱HelloWorld,需與dwr.xml
配置文件中javascript
屬性值一樣,以下兩個文件的順序不能變:
<script type='text/javascript' src='dwr/engine.js'></script> <script type='text/javascript' src='dwr/interface/HelloWorld.js'></script>
使用DWR還可以使用它的一個工具js:
<script type='text/javascript' src='dwr/util.js'></script>
引入此js后,可以使用它的一些簡單的方法,比如獲取元素的值,設置元素的值等,也可以使用普通js或者jquery來獲取:
//獲取指定id元素的值
var name = dwr.util.getValue("helloYYName");
//設置指定id元素的值為data
dwr.util.setValue("helloYYValue", data);
若不是用DWR的util工具,可以不需要引入util.js工具js。
+提示
engine.js
在jar包中,具體位置為:org.directwebremoting
包內
util.js
也在jar包中,具體路徑為:org.directwebremoting.ui.servlet
包內
2.6 啟動項目訪問測試
最終項目目錄結構如下:
啟動項目后訪問:http://localhost:8080/dwr/
,將有如下頁面:
按順序測試並輸入指定的值,最終結果如下:
控制台輸出內容如下:
經測試無誤。
三、原理簡單分析
3.1.訪問頁面時
當訪問帶有DWR頁面的時候,引入js的請求會被,匹配到web.xml
中的DWR的servlet(org.directwebremoting.servlet.DwrServlet):
<servlet> <servlet-name>dwr-invoker</servlet-name> <!-- 接收js的Ajax請求的servlet --> <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>dwr-invoker</servlet-name> <!-- 攔截指定的URL --> <url-pattern>/dwr/*</url-pattern> </servlet-mapping>
servlet會動態創建engine.js
文件,並根據dwr/interface/HelloWorld.js,這種特定路徑的文件名HelloWorld,去DWR配置文件dwr.xml
中去查找相關配置:
<create creator="new" javascript="HelloWorld"> <param name="class" value="yiwangzhibujian.HelloWorld" /> </create>
查找到配置的對象后,並根據對象的所有方法動態創建HelloWorld對象,也會將所有方法生成相應的js方法,生成的HelloWorld.js如下:
if (typeof dwr == 'undefined' || dwr.engine == undefined) throw new Error('You must include DWR engine before including this file'); (function() { if (dwr.engine._getObject("HelloWorld") == undefined) { var p; p = {}; p.helloNN = function(callback) { return dwr.engine._execute(p._path, 'HelloWorld', 'helloNN', arguments); }; p.helloNY = function(callback) { return dwr.engine._execute(p._path, 'HelloWorld', 'helloNY', arguments); }; p.helloYN = function(p0, callback) { return dwr.engine._execute(p._path, 'HelloWorld', 'helloYN', arguments); }; p.helloYY = function(p0, callback) { return dwr.engine._execute(p._path, 'HelloWorld', 'helloYY', arguments); }; dwr.engine._setObject("HelloWorld", p); } })();
可以看到動態生成的對象包含java對象的所有方法,調用js方法會通過底層的Ajax調用相應的Java方法。
3.2 使用原因
- DWR是開源免費的
- 封裝Ajax實現,可以很方便的調用
- 除此以外還有反向Ajax,即服務器推送功能,后續介紹
這一篇簡單的介紹了DWR,並展示了一個js調用Java的例子,可以看出DWR對Ajax封裝的非常好,調用起來很方便。下面一篇將會介紹逆向Ajax的用法。