DWR幫助說明-伺服器端程式的編寫

fightplane發表於2007-09-27

也許朋友們會以為這是DWR官方釋出的什麼幫助,但非常遺憾這不是。現在不少朋友在使用DWR開發專案,我也是其中之一,但苦於關於DWR的幫助文件實在太少,很多問題都不得不自己去鑽研DWR的原始碼才能解決或理解。經過一段時間的苦苦鑽研,總結出那麼一點點心得,現在從DWR原始碼實現的角度詳細講解DWR的使用,寫出來與大家分享。今天我談一談DWR伺服器端程式碼的編寫。

前面我談到,dwr使我們編寫的程式碼完全省略掉了MVC層,也就是說我們可以從過去需要在MVC層做的formvo的資料轉換、為每個頁面訪問提供相應的action和一系統複雜的配置都省略掉了,似乎直接就從頁面到bus了。但是,這樣的省略似乎來得太快了點兒,一下子還真不太適應。我最初就有這樣的感覺,其中一些以前應當在action中執行的功能,現在需要另想辦法,最常見的就是獲取requestresponsesession和許可權校驗。

獲取requestresponsesession

據說在其它一些ajax的產品中沒有提供對requestresponsesession的獲取,需要自己寫程式去取得,但在dwr中就完全可以沒有這個顧慮了。在dwr中有一個WebContextFactory類,靜態呼叫這個類的get()方法就可以得到dwr的另一個類:WebContext。在WebContext中,你可以看到getHttpServletRequest()getHttpServletResponse()getSession()等方法,通過它們就可以順利地得到requestresponsesession了。

雖然dwr可以方便快捷地讓我們獲取requestresponsesession,但另一個問題我覺得值得我們思考:我們應當在哪個層次上獲取它們?我們使用dwr的方便之處是沒有MVC層,也就似乎是說從頁面端直接就到達了bus層。雖然實際並不是這樣,但從頁面到bus之間的工作都是dwr在為我們完成的,我們沒有對這部分編碼。這樣,我們似乎也就可以直接在bus層通過dwr提供的方法直接引用和處理requestresponsesession好 了。當然可以這樣處理,但我認為這樣做不是一個好的設計,因為這樣做違背“不要跟陌生人說話”原則。眾所周知,“不要跟陌生人說話”是軟體設計模式中一個 重要的原則,它要求我們在設計某個類的過程中,不要去訪問與自己職能不相關的類,以便保持自身功能的獨立性。我們傳統的對bus層其職能的定義,應當是實現某個業務功能。為了實現這個業務功能也許需要一些資料,比如從request獲取資料,從資料庫獲取資料。但是這些資料是如何獲取的,都不是bus層關心的問題。它只在意從自己引數中,或者呼叫某個介面來獲得資料,這就是bus的職能。

如果我們在寫bus的時候加入了通過dwr獲取requestresponsesession的程式碼,那麼bus就開始與陌生人說話了,也就是做了一些與自己職能無關的工作,訪問了一些不應該訪問的類。這樣做的後果就是,如果今後我們希望將這些bus重用到別的專案中,而這個專案又不使用dwr,或者在本專案中需要重用某個bus到別的功能中,而這個功能不使用dwr,那麼這樣的設計將使這種重用變為不可能。

說了這麼半天虛的,舉一個例子來實際說明一下該怎樣設計。在一個專案中需要使用requestresponsesession的地方最常用的就是獲取登入使用者的使用者資訊,如他的使用者名稱、所在部門、擁有許可權等。這個功能在各個bus中可能都用得到,而且功能比較固定,因此我們將它抽象出來做成一個公用類。在寫這個公用類前我們先寫一個獲取requestresponsesession的公用類,具體的寫法如下:

java 程式碼
  1. public class Context {   
  2.   
  3.        private static WebContext getContext(){   
  4.   
  5.               return WebContextFactory.get();   
  6.   
  7.        }   
  8.   
  9.        public static HttpServletRequest getRequest(){   
  10.   
  11.               return getContext().getHttpServletRequest();   
  12.   
  13.        }   
  14.   
  15.        public static HttpServletResponse getResponce(){   
  16.   
  17.               return getContext().getHttpServletResponse();   
  18.   
  19.        }   
  20.   
  21.        public static HttpSession getSession(){   
  22.   
  23.               return getContext().getSession();   
  24.   
  25.        }   
  26.   
  27. }   
  28.   

然後寫一個UserInfoUtil的公用類,引用Context來獲得session中的使用者資訊,供其它bus呼叫。你也可以引用Context寫出其它類來獲取和操作requestresponsesession,總之就是不要寫到bus中。

許可權校驗

前面談完了requestresponsesession的問題,緊跟著我們就來談許可權校驗的問題。在dwr中似乎頁面端可以直接就去訪問bus的各個方法,這從資訊保安的角度講是非常危險的。我們必須對頁面訪問bus進行安全校驗。根據前面的思路,這樣的校驗不應當寫在bus中,而是抽象出來形成公用類。就這個問題我在網上搜尋了一下,有不是網友討論過這個問題,總結一下有2種思路:一種是為dwr設計一個filter,另一種是運用aopbus設計攔截器。對比這2種思路,我更欣賞後一種思路,因為它更靈活多變,也更適合與spring結合使用。我們再展開分析一下它的優勢所在吧。

首先,我們可能在不同的專案中會對為專案提供多種許可權校驗的機制,比如通過部門級次進行校驗、通過分配給使用者的功能進行校驗、通過使用者的特殊身份(總經理、局長等)進行校驗等。這些校驗機制並不是每個bus都需要使用的,有的bus使用這種機制,有的bus使用那種機制,有的bus同時使用好幾種機制。

另外,我們還可能出現,一些特殊的功能需要單獨為它設計一個許可權校驗機制,這個機制只作用與它自己。

還有一種情況是許可權校驗機制需要分不同的方法進行校驗,如增刪改一個校驗機制,而查詢是另一種校驗機制。

然後,我們不希望在開發過程中加上許可權校驗機制,這無疑會為我們的除錯增加許多的不便。

總結以上所有對許可權校驗的需求,使用filter似乎有些力不從心,而aop卻完全可以勝任。在系統設計完成以後再通過配置來新增系統所需的諸如許可權校驗、事務處理等功能是aop的基本思想。而Aop可以在spring的配置檔案中配置哪些bus使用哪些校驗攔截器,也可以為一個bus配置多個攔截器。Spring提供了通過bean名稱匹配的方式(諸如*Bus*Service)為所有bus配置攔截器,也可以單獨為某個bus配置攔截器。另外,你還可以採用方法名匹配的方式(諸如create*update*delete*)決定哪些方法採用哪些許可權攔截器。看了這些是不是覺得眼熟呀,對,這種方式正好是與spring的事務攔截器是完全一樣的方式進行操作的。

Dwr的事務處理

我在前面的文章中提到,在頁面端dwr提供了dwr.engine.beginBatch()dwr.engine.endBatch()來進行事務處理。如果你在專案中使用了hibernate,可以在web.xml中新增org.directwebremoting.hibernate.H3SessionAjaxFilter就可以實現hibernate的事務處理了。但我認為這沒有什麼用,因為我們通常在bus層通過spring的事務處理機制就可以完美地完成事務處理了,dwr的事務處理則似乎有些多此一舉。

Dwr的除錯功能

最後我要提到的,就是dwr最重要的,也是dwr提供給我們最好用的一個功能:除錯功能。首先我們要開啟除錯功能,也就是在web.xml中,將DwrServletdebug引數設定為true,然後在瀏覽器中訪問http://[你的專案地址、埠及其專案名]/dwr,就可以顯示出你在dwr中註冊的所有有效的bus,點選某個bus就可以顯示dwr偵測到的該bus的所有方法。如果這些方法使用到某些類引數或返回值,以及哪些方法被你禁用了,在該頁面中都會提示你。另外,在該頁面中還會提示你,要使用該bus,你應當在頁面中引入哪些js。點選這些js的連結並選擇儲存,你還可以看到dwr為你動態生成的js的內容,特別是那個XxxBus.js的內容。這個除錯功能在網上很多dwr的文章中都詳細介紹過,我就不再累贅了。

Dwr的除錯功能完全改變了我們的程式設計方式,至少我是這樣認為的。它讓我們可以將前臺與後臺的編寫和除錯完全分離。首先,我們先編寫後臺程式,就是哪些busdao以及相關的類。在編寫的過程中,我們完全可以不用啟動TomcatWeblogic等應用伺服器,而是編寫main函式直接執行,大大提高我們執行除錯的效率。後臺程式編寫完成以後,通過dwr的除錯頁面在應用伺服器確認所有的bus方法在伺服器端正常執行,就可以在完全不用重啟伺服器的情況下直接編寫前端頁面程式。這樣的程式設計方式完全就沒有了過去一遍一遍重啟伺服器的痛苦,怎能不說是一種完全的改變呢?

除此以外,與其它框架一樣,我們在運用dwr開發專案的時候同樣會出現一些錯誤。在這些錯誤中,有的是因為dwr自身的bug所致。如何解決dwrbug造成的錯誤呢?我將在下一篇文章中討論。

 

相關文章