104
AJAX 的 client/server 溝通機制探究 馮彥文 隨想行動科技

ajax transportation methods

Embed Size (px)

Citation preview

Page 1: ajax transportation methods

AJAX 的 client/server 溝通機制探究

馮彥文隨想行動科技

Page 3: ajax transportation methods

3

這個故事 , 就從兩個技術人在一次研討會中的偶然相遇開始…

Page 4: ajax transportation methods

4

傑克 : Hi 珍妮佛 ,你知道這個 session 最主要是講 ?

Page 5: ajax transportation methods

5

內容主題• AJAX

–利用 AJAX 提高網站與使用者的互動性 (Rich Internet Application)

– User Interface: DHTML–非同步傳輸 : XMLHttpRequest (XHR) 與其他方式 , 與他們的黑暗面

• AJAX Framework–學習如何利用 DWR(Direct Web Remoting) 來簡化 AJAX 與 Java 間的網路存取 , 且為網站增添更多功能

– AJAX / Reverse AJAX

Page 6: ajax transportation methods

6

我們的目標• 即時股市報價

– http://www.marketwatch.com– http://localhost:8080/dwr-reverse/before.jsp– http://localhost:8080/dwr-reverse/after.jsp

Page 7: ajax transportation methods

7

我們的目標• Web 聊天室

– http://gabbly.com/http://www.pocketshark.com/blog/page/tempo/

– http://localhost:8080/dwr-chat/before.jsp– http://localhost:8080/dwr-chat/after.jsp

Page 8: ajax transportation methods

8

What We Will Focus on Here

Browser Compatibility, Cross-Domains, Java Data Marshalling, JSON, JSON-RPC, DOJO, DWR, GWT, iframe, Prototype, Timeout & Error Handling, Reverse AJAX, History & Bookmarks, scriptTag, Web Framework Integration, XHR, XML

Page 9: ajax transportation methods

AJAX 非同步傳輸

1:35

Page 10: ajax transportation methods

10

珍妮佛 : 什麼是 AJAX? 什麼又是非同步傳輸 ?

Page 11: ajax transportation methods

11

AJAX

AsynchronousJavaScriptAndXML

XHTML&CSSDOM

JavaScriptXMLHttpRequest

AJAX = DHTML + XHRAJAX = DHTML + XHR

Page 12: ajax transportation methods

12

Classic Web Applications

From: http://adaptivepath.com/publications/essays/archives/000385.php

Page 13: ajax transportation methods

13

AJAX Web Applications

From: http://adaptivepath.com/publications/essays/archives/000385.php

Page 14: ajax transportation methods

14

傑克 : 那我該如何利用 AJAX 存取遠端網站資料呢 ?

Page 15: ajax transportation methods

15

XHR(XMLHttpRequest)

• JavaScript 版的 HttpConnection• 介面

– open(string url,string asynch): 開啟網頁– send(string): 傳送資料– onreadystatechange: 狀態改變回呼函式– status: HTTP 狀態– responseXML: 回傳的 XML DOM– responseText: 回傳的文字內容

Page 16: ajax transportation methods

16

XHR

• 使用者輸入觸動 XHR

// 建立 XHRrequest = new XMLHttpRequest();// 設定回呼函式request.onreadystatechange=handleResponse;// 開啟連結request.open("GET","http://abc.com",true);// 傳送資料request.send(null);

Page 17: ajax transportation methods

17

XHR

• 接收資料後立刻更新 UIfunction handleResponse() { // 檢查 XHR 狀態 if(request.readyState == 4){ // 檢查 http 狀態 if(request.status == 200){ // 讀取回傳 XML 資料 var doc = request.responseXML; // 取得網頁上需被更新的 node 位置 var node = document.getElementById(“resp"); // 設定該 node 的內容 node.innerHTML = doc.documentElement.childNodes[0].nodeValue; } }}

Page 18: ajax transportation methods

18

DEMO: Hello World

http://localhost:8080/xhr/index.jsp

Page 19: ajax transportation methods

Tips & Tricks about XHR

1:40

Page 20: ajax transportation methods

20

珍妮佛 : 傑克 , 這真是太神奇了 , 但傳輸的資料一定要是 XML 格式嗎 ?

Page 21: ajax transportation methods

21

XHR 接受的資料型態•不 , XHR 除了 XML 資料之外 , 還

可以傳送 text, 所以也包括了 HTML, JavaScript (JSON)

[{author:‘tempo’, title:‘ 智者的對談 '},{author:‘browser,koji’, title:‘JSP 技術手冊 '},{author:‘caterpillar’, title:‘Spring 技術手冊 '},{author:‘piggy’, title:’Java2 全方位學習’ ];

Page 22: ajax transportation methods

22

傑克 : 那所有的瀏覽器都有支援 XHR 嗎 ?

Page 23: ajax transportation methods

23

瀏覽器支援• XHR 支援以下瀏覽器

– IE 5.0+– Mozilla 1.0+– Safari 1.2– Konqueor– Opera 8.0

• 但不同的瀏覽器 XHR 建立方式不同– IE: ActiveX– Others: JavaScript

Page 24: ajax transportation methods

24

瀏覽器支援function httpRequest(reqType,url){ if(window.XMLHttpRequest){ // Mozilla, Opera, Safari, … request = new XMLHttpRequest(); } else if (window.ActiveXObject){ // IE request=new ActiveXObject("Msxml2.XMLHTTP"); if (!request){ request=new ActiveXObject("Microsoft.XMLHTTP"); } } if(request){ … } else { alert("Your browser does not permit the use of all "+ "of this application's features!"); }}

Page 25: ajax transportation methods

25

珍妮佛 : 真奇怪 , 我使用 XHR, 瀏覽器卻一直跳出安全性問題 ?

Page 26: ajax transportation methods

26

跨網域支援• 有可能是其他問題 , 但 XHR 限制僅能

存取該網站上的資料 , 無法存取其他網站的資料

• For example, 若此網頁的網址為 http://www.abc.com/test.jsp, 則 XHR:– 不可存取 : test.abc.com/*, abc.com/*– 可存取 : www.abc.com/*

• AJAX SOA?

Page 27: ajax transportation methods

27

傑克 : 少來了 tempo, 明明除了 XHR 之外 , 還有其它方式來存取網站資料

Page 28: ajax transportation methods

28

<iframe> 與 <script>• 是的 , 利用 <iframe> 與 <script> 也可以

達到相同的功能 , 但需要轉幾個彎

Page 29: ajax transportation methods

29

<iframe> 與 <script> 使用• <iframe>

• <script>var sObj = document.createElement('script');sObj.src = ‘http://www.abc.com’;document.body.appendChild( sObj );

var sObj = document.createElement('iframe');sObj.src = ‘http://www.abc.com’;sObj.onload = function() { iframe_loaded( sObj ); };document.body.appendChild( sObj );

Page 30: ajax transportation methods

30

<iframe> 與 <script> 資料接收• <iframe>

– 回傳資料為 HTML 格式• <script>

– 回傳資料為 JavaScript 格式• 但都可以經過額外的步驟轉換為 XML 或 J

avaScript

Page 31: ajax transportation methods

31

<iframe> 與 <script> 優缺點• 優點

– 可以跨網域存取資料 , 不像 XHR 有限制– <iframe> 瀏覽過的網頁會被加入瀏覽器的歷

史紀錄內– 支援較多的瀏覽器

• 缺點– 使用起來較繁瑣– 僅支援 HTTP GET

Page 32: ajax transportation methods

32

tempo: 那我來做個整理吧

Page 33: ajax transportation methods

33

各種方法比較

Page 34: ajax transportation methods

34

小細節需要注意• 三種傳輸方式

– XHR, <iframe>, <script>• 三種資料格式

– XML, HTML, JavaScript• 跨網域問題• 瀏覽器支援問題• 上一頁 / 下一頁與書籤問題 *

Page 35: ajax transportation methods

35

珍妮佛 : 好吧 tempo, 這太複雜了 , 我只是想要存取網站上的資料而已

Page 36: ajax transportation methods

36

透過 AJAX Framework 來做非同步傳輸• XHR, <iframe>, <script> 各有不同的優點

與缺點• 瀏覽器有不同的 bugs 與標準• 自行維護非同步傳輸底層不容易

Page 37: ajax transportation methods

37

透過 AJAX Framework 來做非同步傳輸•現有的 AJAX Framework 都有提供自己的 XHR Utility 或包裝– Framework: Google Web Toolkit, ZK, Dojo, …

– RPC: DWR, JSON-RPC, …– Libraries: Prototype, …

• DWR 是其中最專業也是支援最廣的 AJAX 非同步傳輸 Framework

Page 38: ajax transportation methods

Direct Web Remoting

1:50

Page 39: ajax transportation methods

39

傑克 : 什麼是 DWR 呢 ?

Page 40: ajax transportation methods

40

DWR(Direct Web Remoting)• RPC-Style AJAX• Easy AJAX for Java• Easy to integrate• AJAX:

– Expose Java to the Browser• Reverse AJAX:

– Expose JavaScript to the Server

Page 41: ajax transportation methods

41

DWR

From: http://getahead.ltd.uk/dwr/overview/dwr

Page 42: ajax transportation methods

42

珍妮佛 : 我也想試試 DWR, 我該如何安裝呢 ?

Page 43: ajax transportation methods

43

Step 1: Download

•從網站下載 DWR: http://getahead.ltd.uk/dwr/download

• Copy dwr.jar into WEB-INF/lib

2:00

Page 44: ajax transportation methods

44

Step 2: web.xml

<servlet> <servlet-name>dwr-invoker</servlet-name> <display-name>DWR Servlet</display-name> <servlet-class> org.directwebremoting.servlet.DwrServlet </servlet-class> <init-param> <param-name>debug</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>

• 修改 web.xml, 新增 DwrServlet

Page 45: ajax transportation methods

45

Step 3: dwr.xml

<dwr>

<allow>

<create creator="new" javascript="JDate"> <param name="class" value="java.util.Date"/> </create>

</allow>

</dwr>

• 將遠端 Java 物件註冊到 dwr.xml

Page 46: ajax transportation methods

46

DEMO: Installation

http://localhost:8080/dwr-minimal/dwr/

Page 47: ajax transportation methods

47

DWR 除錯視窗• 在 web.xml 設定 init-param, ‘debug’ =

true

• 顯示註冊在 dwr.xml 的物件與提供直接測試用

• 請不要在正式環境使用 !!!

<init-param> <param-name>debug</param-name> <param-value>true</param-value></init-param>

Page 48: ajax transportation methods

48

建民 : 那 tempo, 你應該要講怎麼做 Hello World 了吧 ?

2:05

Page 49: ajax transportation methods

49

Step1: 建立伺服器端的 Java 物件package com.willmobile.ajaxtm;

public class HelloWorld { public String sayHelloWorldTo(String name) { return "Hello World " + name + "!"; }}

Page 50: ajax transportation methods

50

Step2: 在 dwr.xml 中註冊類別

<dwr> <allow> <create creator="new“ javascript="HelloWorld" scope="page"> <param name="class" value="com.willmobile.ajaxtm.HelloWorld" /> </create> </allow></dwr>

• 在 dwr.xml 的 <allow> 內建立 <create>

Page 51: ajax transportation methods

51

Step3: 在網頁中 include JavaScript

<head><script type='text/javascript' src='/dwr-helloworld/dwr/interface/HelloWorld.js'/><script type='text/javascript‘ src='/dwr-helloworld/dwr/engine.js‘/><script type='text/javascript‘ src='/dwr-helloworld/dwr/util.js‘/></script></head>

• engine.js 與 util.js 是 dwr 的公用 script• HelloWorld.js 是我們註冊的遠端物件 script

Page 52: ajax transportation methods

52

Step4: 撰寫 client 端 JavaScript

<head><script type="text/javascript">window.onload = function() { functon callback(str) { $('output').innerHTML = str; } HelloWorld.sayHelloWorldTo("JavaTwo 2006", callback);}</script></head>

Page 53: ajax transportation methods

53

遠端物件方法呼叫方式• 參數與一般呼叫方式相同• 回傳值使用 callback function, 放在最後一個參數

• 用 Meta-data Object 定義 callback function

public class Remote { public String getData(int index) { ... }}

function handleGetData(str) { alert(str);}

Remote.getData(42, handleGetData);

Page 54: ajax transportation methods

54

Demo: Hello World

http://localhost:8080/dwr-helloworld/http://localhost:8080/dwr-helloworld/dwr/

Page 55: ajax transportation methods

Tips & Tricks about DWR

2:15

Page 56: ajax transportation methods

56

傑克 : 可以讓遠端 Java 物件存放在 session 或 application scope 嗎 ?

Page 57: ajax transportation methods

57

設定遠端物件的 Scope

• 物件的 scope 可以透過 dwr.xml 內的 create 屬性設定– application, session, request, page

<dwr> <allow> <create creator="new“ javascript="HelloWorld" scope="page"> <param name="class" value="com.willmobile.ajaxtm.HelloWorld" /> </create> </allow></dwr>

Page 58: ajax transportation methods

58

珍妮佛 : 參數可以是自訂的類別嗎 ?

Page 59: ajax transportation methods

59

Converters

•定義在 dwr.xml 中描述 remote 物件

• var r = Remote.method(param);

Uses a Converter

Uses a Creator

From: http://getahead.ltd.uk/dwr/overview/dwr

Page 60: ajax transportation methods

60

Converters

•自動轉換– Primitive Type ( 與他們對應的 class 型態 )– String– Date

•預設 Converters– Bean/Object Converter– Array/Collection Converter– Dom Objects– Enum Converter

Page 61: ajax transportation methods

61

Converters設定

<dwr> <allow> <create> … </create> <convert converter="bean“ match="com.willmobile.ajaxtm.User"> </convert> </allow></dwr>

• 在 dwr.xml 的 <allow> 內建立 <convert>

Page 62: ajax transportation methods

62

傑克 : 任何遠端 Java 物件上的方法都可以呼叫嗎 ?

Page 63: ajax transportation methods

63

<include>, <exclude>

• 可在 dwr.xml 中設定遠端 Java 物件存取的權限

<dwr> <allow> <create creator="new“ javascript="HelloWorld" scope="page"> <param name="class" value="com.willmobile.ajaxtm.HelloWorld" /> <exclude method=“noUse"/> </create> <convert converter="bean“ match="com.willmobile.ajaxtm.User"> <param name="exclude" value="password"/> </convert> </allow></dwr>

Page 64: ajax transportation methods

64

tempo: 那該輪到做一個 Web Form 來試試看

2:20

Page 65: ajax transportation methods

65

Step1: 建立伺服器端的 Java 物件public class User { private String id; private String password; private String name; private String title; …}

Page 66: ajax transportation methods

66

Step2: 建立伺服器端的 Java 物件public class UserManager { private final List<User> users = new ArrayList<User>();

public synchronized void add(User user) { users.add(user); }

public synchronized List<User> getAll() { return new ArrayList<User>(users); }}

Page 67: ajax transportation methods

67

Step3: client scriptfunction addUser() {

var user = { id:"", name:"", title:"" };DWRUtil.getValues(user);UserManager.add(user);

UserManager.getAll(fillTable);}

var cellFuncs = [ function(data) { return data.id; }, function(data) { return data.name; }, function(data) { return data.title; }];

function fillTable(users) { DWRUtil.removeAllRows("usersBody"); DWRUtil.addRows("usersBody", users, cellFuncs);}

Page 68: ajax transportation methods

68

Demo: DWR Form

http://localhost:8080/dwr-form/

Page 69: ajax transportation methods

Reverse AJAX

2:25

Page 70: ajax transportation methods

70

珍妮佛 : 我也會做 jsp 的聊天室呀 , 你前面的 Demo 有比較好嗎 ?

Page 71: ajax transportation methods

71

Reverse AJAX

• AJAX( 與一般 WEB 應用 )–由瀏覽器發動每個需求 , 伺服器不能主動傳給瀏覽器任何資料

– Pull Model• Reverse AJAX

–伺服器可主動傳送資訊至瀏覽器顯示或執行– Push Model ( 但其實是用 pull 模擬 )

•Polling•Comet(Long Live HTTP)

Page 72: ajax transportation methods

72

Polling瀏覽器 伺服器

N秒送出一個 request

1. 新資料到

2. 新資料傳至瀏覽器

3. 顯示

req1

req2

req3

req4

Page 73: ajax transportation methods

73

Comet瀏覽器 伺服器

1. 新資料到2. 新資料傳至瀏覽器

3. 顯示

req1

req2

Page 74: ajax transportation methods

74

Reverse AJAX

• DWR–將這些複雜的操作隱藏起來– Comet(Long Live HTTP)– Polling– Server Push JavaScript 至 Client

ScriptSession.addScript("alert('Hi')");

Page 75: ajax transportation methods

75

Reverse AJAX

•適合需要即時回應的網路應用–股市資訊–線上遊戲–聊天交友–會員客戶服務

Page 76: ajax transportation methods

76

珍妮佛 : 我也想做像前面 Demo 那樣的聊天室 ~~

Page 77: ajax transportation methods

77

Step1: 建立伺服器端的 Java 物件public void addMessage(String text) {…final WebContext wctx = WebContextFactory.get();

// For all the browsers on the current page:String currentPage = wctx.getCurrentPage();Collection sessions = wctx.getScriptSessionsByPage(currentPage);

DwrUtil utilAll = new DwrUtil(sessions);utilAll.removeAllOptions("chatlog");utilAll.addOptions("chatlog", messages, "text");}

Page 78: ajax transportation methods

78

Step1: 建立伺服器端的 Java 物件<script type="text/javascript">window.onload = function() { DWREngine.setReverseAjax(true); Chatroom.getAllMessages(function(messages) { DWRUtil.removeAllOptions('chatlog'); DWRUtil.addOptions( 'chatlog', messages, 'text'); });}

function sendMessage() { Chatroom.addMessage(DWRUtil.getValue("text"));}</script>

Page 79: ajax transportation methods

79

Demo: DWR Chat

http://localhost:8080/dwr-chat/before.jsphttp://localhost:8080/dwr-chat/after.jsp

Page 80: ajax transportation methods

80

傑克 : 那你之前 Demo 的股市報價 , 也是用同一種技術囉 ?

2:30

Page 81: ajax transportation methods

81

Step1: 建立伺服器端的 Java 物件private class SendTickerDataTask extends TimerTask { public void run() { ServerContext sctx = ServerContextFactory.get(servletContext); Collection sessions = sctx.getScriptSessionsByPage( “/dwr-reverse/after.jsp”);

DwrUtil pages = new DwrUtil( sessions, servletContext); pages.setValue(symbol, RandomStockSnapshot. getRandomStockSnapshotString(symbol)); }}

Page 82: ajax transportation methods

82

Demo: DWR Reverse

http://localhost:8080/dwr-reverse/before.jsp http://localhost:8080/dwr-reverse/after.jsp

Page 83: ajax transportation methods

Web Framework Integration

2:35

Page 84: ajax transportation methods

84

珍妮佛 : 我不想呼叫物件 , 我想把整個網頁 include 進來 , 這可以嗎 ?

Page 85: ajax transportation methods

85

AJAX Includes

• 可以 , DWR 提供 Server-side Include• Server

• Browser

public String getInclude() { return WebContextFactory.get() .forwardToString("/forward.jsp");}

function update() { Demo.getInclude(function(html) { DWRUtil.setValue("somediv", html); });

Page 86: ajax transportation methods

86

傑克 :這樣也行 , 那我想要呼叫我伺服器上的 spring beans, 不會也可以吧 ?

Page 87: ajax transportation methods

87

Spring Integration

• SpringCreator

• web.xml

<allow> <create creator="spring" javascript="Fred"> <param name="beanName" value="Shiela"/> </create></allow>

<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/classes/beans.xml</param-value></context-param>

Page 88: ajax transportation methods

88

珍妮佛 :好吧 , 那像 Struts, Webwork 應該也不是問題囉 ?

Page 89: ajax transportation methods

89

Struts Integration

• StrutsCreator

• Webwork– 整合至 Action 層 , 可透過 JavaScript 直接

將 form 丟給 Action

<allow> <create creator="struts" javascript="Fred"> <param name="beanName" value="Shiela"/> </create></allow>

Page 90: ajax transportation methods

其他的功能

2:40

Page 91: ajax transportation methods

91

傑克 : 我想要連續呼叫三個遠端函式 , 這樣使用者會等比較久嗎 ?

Page 92: ajax transportation methods

92

Batching

• 會的 , 所以若需要將數個 dwr 功能一次送出 , 請將需要在同一個交易內的功能放到 Batch 中

beginBatch();…endBatch();

Page 93: ajax transportation methods

93

珍妮佛 : 我看你的網頁右上方都有像 gmail 一樣的 loading message, 我也要

Page 94: ajax transportation methods

94

Loading Message

• 請在網頁 onLoad 時呼叫 useLoadingMessage() 即可

DWRUtils.useLoadingMessage();OrDWRUtils.useLoadingMessage(‘Waiting…’);

Page 95: ajax transportation methods

95

傑克 : 你都沒有提到錯誤處理機制 :(

Page 96: ajax transportation methods

96

Error Handling

• Global Error (Exception) Handling

• Meta Data

function handler(msg) { alert(msg);}

DWREngine.setErrorHandler(handler);

Remote.method(params, { callback:function(data) { ... }, errorHandler:handler});

Page 97: ajax transportation methods

97

傑克 : 哇 , DWR/AJAX 真棒 , 可是 back/forward 鍵沒用了 :(

Page 98: ajax transportation methods

98

瀏覽器歷史紀錄問題

• XHR 或是 <script> 都無法將連線網頁加入瀏覽器歷史紀錄內

• Really Simple History– http://

codinginparadise.org/projects/dhtml_history/README.html

Page 99: ajax transportation methods

99

珍妮佛 : 以上提到的方法所有瀏覽器都支援嗎 ?

Page 100: ajax transportation methods

100

瀏覽器支援• DWR 支援以下瀏覽器

– IE 5.5+– Firefox 1.0+– Mozilla 1.7+– Safari 1.2+– Konqueor– Opera 7.5.4+ ( 但現在不支援 Reverse AJAX)

Page 101: ajax transportation methods

101

傑克 : 我已經有使用其他 framework 了 , 那我該如何整合 DHR 呢 ?

Page 102: ajax transportation methods

102

DWR 與其它 AJAX Framework

• JavaScript Libraries 不會有影響– Dojo Toolkit– Prototype– Script.aculo.us

• AJAX Framework 則請使用原本提供的存取方式– GWT– ZK

2:45

Page 103: ajax transportation methods

Thank you!

如果你流落荒島 , 但是只能帶一個 AJAX Framework, 建議你帶 DWR 馮彥文[email protected]

Page 104: ajax transportation methods

104

我想請教關於 ..