DWR is a Java open source library which allows you to write Ajax web sites.
It allows code in a browser to use Java functions running on a web server just as if it was in the browser.
DWR consists of two main parts:
- A Java Servlet running on the server that processes requests and sends responses back to the browser.
- JavaScript running in the browser that sends requests and can dynamically update the webpage.
DWR works by dynamically generating Javascript based on Java classes. The code does some Ajax magic to make it feel like the execution is happening on the browser, but in reality the server is executing the code and DWR is marshalling the data back and forwards.
This method of remoting functions from Java to JavaScript gives DWR users a feel much like conventional RPC mechanisms like RMI or SOAP, with the benefit that it runs over the web without requiring web-browser plug-ins.
Java is fundamentally synchronous where Ajax is asynchronous. So when you call a remote method, you provide DWR with a callback function to be called when the data has been returned from the network.
The diagram shows how DWR can alter the contents of a selection list as a result of some Javascript event like onclick.
DWR dynamically generates an AjaxService class in Javascript to match some server-side code. This is called by the eventHandler. DWR then handles all the remoting details, including converting all the parameters and return values between Javascript and Java. It then executes the supplied callback function (populateList) in the example below which uses a DWR utility function to alter the web page.
DWR helps you in producing highly interactive web-sites by providing some Javascript libraries to help with DHTML and by giving you a set of examples to copy from.
For details on how to get started with DWR see the getting started guide and download instructions.
//---------------------------以下是中文介紹-0--------------------------------------------------------------
這段時間較閑,研究了一番dwr.發現dwr實現的AJAX有些地方確實很是先進.比如動態生成javascript代碼;隱藏的http協議;javascript于java代碼交互的是javascript對象(或字符串)等.
以下是我臨時譯的一些東西.本來想全譯,發現dwr實在是簡單,就隨便寫了.英文居差,現一把.
1、DWR: Easy AJAX for JAVA
作為一個java open source library,DWR可以幫助開發人員完成應用AJAX技術的web程序。它可以讓瀏覽器上的javascript方法調用運行在web服務器上java方法。
DWR主要由兩部門組成。javascript與web服務器通信并更新web頁;運行在web服務器的Servlet處理請求并把響應發回瀏覽器。
DWR 采用新穎的方法實現了AJAX(本來也沒有確切的定義),在java代碼基礎上動態的生成javascript代碼。web開發者可以直接調用這些 javascript代碼,然而真正的代碼是運行在web服務器上的java code。出與安全考慮,開發者必須配置哪些java class暴露給DWR.(dwr.xml)
這種從(java到javascript)調用機制給用戶一種感覺,好象常規的RPC機制,或RMI or SOAP.但是它運行在web上,不需要任何瀏覽器插件。
DWR 不認為瀏覽器和web服務器之間協議重要,把系統界面放在首位。最大挑戰是java method call的同步特征與ajax異步特性之間的矛盾。在異步模型里,結果只有在方法結束后才有效。DWR解決了這個問題,把回調函數當成參數傳給方法,處理完成后,自動調用回調方法。
這個圖表顯示了,通過javascript事件,DWR能改變select的內容,當然這些內容由 java代碼返回。 javascript函數Data.getOptions(populateList)由DWR動態生成,這個函數會調用java class Data類的方法。DWR處理如何遠程調用,包括轉換所有的參數和返回的結果(javascript\java)。java方法執行完后,執行回調方法 populateList。在整個過程中我們就想在用本地的方法一樣。
2、Getting Started
廢話少說,試試就ok了。
web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!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 id="dwr">
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
</web-app>
dwr.xml 與web.xml同目錄
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN" "http://www.getahead.ltd.uk/dwr/dwr10.dtd">
<dwr>
<allow>
<create creator="new" javascript="JDate">
<param name="class" value="java.util.Date"/>
</create>
</allow>
</dwr>
index.html
<html>
<head>
<title>DWR - Test Home</title>
<script type='text/javascript' src='dwr/interface/JDate.js'></script>
<script type='text/javascript' src='dwr/engine.js'></script>
<script>
function init(){
JDate.getYear(load);
}
function load(data){
alert(data+1900+'年')
}
</script>
</head>
<body onload="init()">
</body>
</html>
dwr.jar 下載放lib下
完了,什么,夠了,就這些。訪問ok!
3、Examples
http://www.aboutmyhealth.org/ 這不是Google Suggest嗎!ok.
4、源碼淺析
dwr的設計很象webwork2的設計,隱藏http協議,擴展性,兼容性及強。
通過研究uk.ltd.getahead.dwr.DWRServlet這個servlet來研究下dwr到底是如何工作滴。
java代碼:? |
web.xml配置 <servlet> ? ? <servlet-name>dwr-invoker</servlet-name> ? ? <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class> ? </servlet> ? <servlet-mapping> ? ? <servlet-name>dwr-invoker</servlet-name> ? ? <url-pattern>/dwr/*</url-pattern> </servlet-mapping>
|
這樣所有的/dwr/*所有請求都由這個servlet來處理,它到底處理了些什么能。我們還以上面最簡單的例子來看。
1、 web服務器啟動,DWRServlet init()方法調用,init主要做了以下工作。
設置日志級別、實例化DWR用到的單例類(這些類在jvm中只有一個實例對象)、讀去配置文件(包括dwr.jar包中的dwr.xml,WEB-INF/dwr.xml. config*.xml)。
2、請求處理
DWRServlet.doGet, doPost方法都調用processor.handle(req, resp)方法處理。Processor對象在init()方法中已經初始化了。
java代碼:? |
publicvoid handle(HttpServletRequest req, HttpServletResponse resp) ? ? ? ? throwsIOException ? ? { ? ? ? ? String pathinfo = req.getPathInfo(); ? ? ? ? if(pathinfo == null || pathinfo.length() == 0 || pathinfo.equals("/")) ? ? ? ? { ? ? ? ? ? ? resp.sendRedirect(req.getContextPath() + req.getServletPath() + '/' + "index.html"); ? ? ? ? }else ? ? ? ? if(pathinfo != null && pathinfo.equalsIgnoreCase("/index.html")) ? ? ? ? { ? ? ? ? ? ? doIndex(req, resp); ? ? ? ? }else ? ? ? ? if(pathinfo != null && pathinfo.startsWith("/test/")) ? ? ? ? { ? ? ? ? ? ? doTest(req, resp); ? ? ? ? }else ? ? ? ? if(pathinfo != null && pathinfo.equalsIgnoreCase("/engine.js")) ? ? ? ? { ? ? ? ? ? ? doFile(resp, "engine.js", "text/javascript"); ? ? ? ? }else ? ? ? ? if(pathinfo != null && pathinfo.equalsIgnoreCase("/util.js")) ? ? ? ? { ? ? ? ? ? ? doFile(resp, "util.js", "text/javascript"); ? ? ? ? }else ? ? ? ? if(pathinfo != null && pathinfo.equalsIgnoreCase("/deprecated.js")) ? ? ? ? { ? ? ? ? ? ? doFile(resp, "deprecated.js", "text/javascript"); ? ? ? ? }else ? ? ? ? if(pathinfo != null && pathinfo.startsWith("/interface/")) ? ? ? ? { ? ? ? ? ? ? doInterface(req, resp); ? ? ? ? }else ? ? ? ? if(pathinfo != null && pathinfo.startsWith("/exec")) ? ? ? ? { ? ? ? ? ? ? doExec(req, resp); ? ? ? ? }else ? ? ? ? { ? ? ? ? ? ? log.warn("Page not found. In debug/test mode try viewing /[WEB-APP]/dwr/"); ? ? ? ? ? ? resp.sendError(404); ? ? ? ? } ? ? }
|
哦。這些恍然大悟。dwr/*處理的請求也就這幾種。
(1)dwr/index.html,dwr/test/這種只能在debug模式下使用,調試用。
dwr/engine.js,dwr/util.js,dwr/deprecated.js當這個請求到達,從dwr.jar包中讀取文件流,響應回去。(重復請求有緩存)
(2)當dwr/interface/這種請求到來,(例如我們在index.html中的 <script type='text/javascript' src='dwr/interface/JDate.js'></script>)DWR做一件偉大的事。把我們在WEB- INF/dwr.xml中的
<create creator="new" javascript="JDate">
<param name="class" value="java.util.Date"/>
</create>
java.util.Date轉化為javascript函數。
http://localhost:port/simpledwr/dwr/interface/JDate.js看看吧。
細節也比較簡單,通過java反射,把方法都寫成javascript特定的方法。(我覺得這些轉換可以放到緩存里,下次調用沒必要再生成一遍,不知道作者為什么沒這樣做)。
(3)dwr/exec
javascript調用方法時發送這種請求,可能是XMLHttpRequest或IFrame發送。
當然,javascript調用的方法簽名與java代碼一致,包括參數,還有javascript的回調方法也傳到了服務器端,在服務器端很容易實現?;卣{方法的java的執行結果 返回類似 <script>callMethod(結果)<script>的javascript字符串,在瀏覽器執行。哈,一切就這么簡單,巧妙。
dwr的設計構思很是巧妙。
第一、把java類轉化為javascript類由dwr自動完成,只需簡單的配置。
第二、應用起來極其簡單。開發者不要該服務器代碼就可以集成。
第三、容易測試。和webwork一樣,隱藏的http協議。
第四、及強擴展性。例如與spring集成,只需修改一點代碼。
第五、性能。就我與jason,等簡單比較,dwr性能可能是最好的。
第六、自動把java對象轉化為javascript對象,并且及易擴展。