[size=large][/size][align=center][/align]本人對dwr 中文文檔關於dwr.xml做的一個整理,純粹體力活,有用得著的朋友別忘頂一下,留個連絡方式一起交流學習!
dwr.xml是DWR的設定檔。預設情況下,應該把它放到WEB-INF目錄(web.xml的目錄)下
建立dwr.xml檔案
dwr.xml檔案的結構如下:
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN" "http://www.getahead.ltd.uk/dwr/dwr10.dtd"><dwr> <!-- init is only needed if you are extending DWR --> <init> <creator id="..." class="..."/> <converter id="..." class="..."/> </init> <!-- without allow, DWR isn't allowed to do anything --> <allow> <create creator="..." javascript="..."/> <convert converter="..." match="..."/> </allow> <!-- you may need to tell DWR about method signatures --> <signatures> ... </signatures></dwr>術語
這裡是一些必須理解的術語 - 參數會被converted,遠程Bean會被created。所以如果你有一個叫A的bean,它有一個方法叫A.blah(B) 那麼你需要一個A的creator和一個B的converter。
一:<allow>
allow段落裡面定義的試DWR可以建立和轉換的類。
二:Creators
dwr.xml檔案中的create元素的結構如下:
<allow> <create creator="..." javascript="..." scope="..."> <param name="..." value="..."/> <auth method="..." role="..."/> <exclude method="..."/> <include method="..."/> </create> ...</allow>這裡的多數元素都是可選的 - 你真正必須知道的是指定一個creator和一個javascript名字。
creator屬性 是必須的 - 它用來指定使用那種創造器。
預設情況下DWR1.1有8種創造器。它們是:
new: 用Java的new關鍵字創造對象。
none: 它不建立對象,看下面的原因。 (v1.1+)
scripted: 通過BSF使用指令碼語言建立對象,例如BeanShell或Groovy。
spring: 通過Spring架構訪問Bean。
jsf: 使用JSF的Bean。 (v1.1+)
struts: 使用Struts的FormBean。 (v1.1+)
pageflow: 訪問Beehive或Weblogic的PageFlow。 (v1.1+)
如果你需要寫自己的創造器,你必須在init部分註冊它。
javascript屬性 用於指定瀏覽器中這個被創造出來的對象的名字。你不能使用Javascript的關鍵字。
scope屬性 非常類似servlet規範中的scope。 它允許你指定這個bean在什麼生命範圍。選項有"application", "session", "request" 和"page"。這些值對於Servlet和JSP開發人員來說應該相當熟悉了。
scope屬性是可選的。預設是"page"。如果要使用"session"需要cookies。當前的DWR不支援ULR重寫。
param元素 被用來指定創造器的其他參數,每種構造器各有不同。例如,"new"創造器需要知道要建立的物件類型是什麼。每一個創造器的參數在各自的文檔中能找到。請查看上面的連結。
include和exclude元素 允許創造器來限制類中方法的訪問。一個創造器必須指定include列表或exclude列表之一。如果是include列表則暗示預設的存取原則是"拒絕";如果是exclude列表則暗示預設的存取原則是"允許"。
例如要拒絕防範除了setWibble()以外的所有方法,你應該把如下內容添加到dwr.xml中。
<create creator="new" javascript="Fred"> <param name="class" value="com.example.Fred"/> <include method="setWibble"/></create>對於加入到create元素中的類的所有方法都是預設可見的。
auth元素 允許你指定一個J2EE的角色作為將來的存取控制檢查:
<create creator="new" javascript="Fred"> <param name="class" value="com.example.Fred"/> <auth method="setWibble" role="admin"/></create>
--------------------------------------------------------------------------------
new創造器在DWR中已經預設聲明了:<creator id="new" class="uk.ltd.getahead.dwr.create.NewCreator"/> 。你不需要在dwr.xml檔案中添加這段話,它已經存在於DWR的內部dwr.xml檔案中了。
這個創造器通過類預設的夠早函數創造對象執行個體。用new創造器有一些好處:
安全:DWR創造的對象生存的事件越短,多次調用中間的值不一致的錯誤機會越少。
記憶體消耗低: 如果你的網站使用者量非常大,這個創造器可以減少VM的記憶體溢出。
你可以通過下面的方式使用new創造器來創造遠程調用Bean:
<allow> <create creator="new" javascript="Blah"> <param name="class" value="java.util.Date"/> </create> ... </allow>這些代碼把 java.util.Date 映射成Javascript,並且命名為Blah,所以在Javascript中當你調用Blah.toString(reply) 那麼一個新的 java.util.Date 就會通過預設的建構函式創造出來, 然後 toString() 方法被調用, 然後結果資料返回給reply方法(在這個例子中date是字串格式)。
--------------------------------------------------------------------------------
none'創造器不建立任何對象 - 它會假設你不需要建立對象。這有可能是對的,有兩個原因。
你可能在使用的scope不是"page"(看上面),並在在前面已經把這個對象建立到這個scope中了,這時你就不需要再建立對象了。
還有一種情況是要調用的方法是靜態,這時也不需要建立對象。DWR會在調用建立器之前先檢查一下這個方法是不是靜態。
對於上訴兩種情況,你仍然需要class參數,用來告訴DWR它是在操作的物件類型是什麼。
--------------------------------------------------------------------------------
scripted創造器在DWR中已經預設聲明了:<creator id="script" class="uk.ltd.getahead.dwr.create.ScriptedCreator"/>
這個創造器用BSF來執行指令碼得到Bean,例如:
<allow> ... <create creator="script" javascript="EmailValidator"> <param name="language" value="beanshell"/> <param name="script"> import org.apache.commons.validator.EmailValidator; return EmailValidator.getInstance(); </param> </create> ...</allow>script創造器有如下參數:
參數 DWR版本 描述
language 1.0 指令碼語言,字串,例如'beanshell'. (必需)
script 1.0 要執行的指令碼。 (必需,除非scriptPath參數存在)
scriptPath 1.1 指令檔路徑。 (必需,除非script參數存在)
reloadable 1.1 是否檢測指令檔的改動,以重新載入 (可選, 預設true)
class 1.0 創造出對象的類型(可選). 如果沒有DWR通過創造器得到類型。
需要瞭解的主題
要使用這個創造器,你需要把一些輔助庫放到WEB-INF/lib檔案夾下:BSF的jar包,你要用的指令碼語言的jar包。
當一個類是用script創造出來的,並且scope是session或application,如果你的指令碼改變,session中的類和script中的類就不一致了。這樣會出現錯誤。雖然web容器不用重啟,但是使用者需要先登出(或以某種方式清空session),然後再登入。
當clazz參數不為空白,並且用來創造新執行個體,DWR簡單的調用 class.newInstance() 方法。這種方法是沒問題的,除非指令碼正在用某個參數建立一個類,或者調用某個函數來配置這個類。 不幸的是,每次請求都要重新運行script並造成上面的問題。
--------------------------------------------------------------------------------
創造器
讓DWR和Spring一起工作的步驟
確認你用的是最新版的DWR。Spring創造器已經有了變化,所以你最好檢查一下DWR的最新版本。
確認你查看過開始指南中的內容。
確認你的Spring的Bean在DWR外面運行良好。
配置DWR和Spring一起工作。 (看下面)
查看示範頁面: http://localhost:8080/[ YOUR-WEBAPP ]/dwr ,檢查spring的Bean是否出現。
DWR對於Spring沒有運行期依賴,所以如果你不使用Spring那麼Spring的支援不會產生任何影響到。
The SpringCreator
這個創造器會尋找spring的中配置的Bean,用Spring去建立它們。如果你已經在使用Spring,那麼這個創造器會非常有用。
你可以通過下面的方式來建立遠程調用的Bean:
<allow> ... <create creator="spring" javascript="Fred"> <param name="beanName" value="Shiela"/> </create> </allow>尋找你的Spring配置
有三種方式尋找設定檔:
ContextLoaderListener
最簡單的方式是使用org.springframework.web.context.ContextLoaderListener。你不必使用所有的Spring-MVC功能,只需要這個Listener就夠了,所以這是個不錯的方案。你需要在WEB-INF/web.xml中做如下配置:
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/classes/beans.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener>我能找到的ContextLoaderListener的最好的文檔就是javadoc。如果你知道還有更好的文檔,請告知我。
Rob Sanheim 指出還有一個能深入瞭解ContextLoaderListener的文檔。
使用location*參數
如果你要在dwr.xml中指定使用哪些bean,你可以使用location*參數。你可以指定任意多個檔案,只要參數以location開始並且唯一即可。例如:location-1, location-2。這些location被用做Spring的ClassPathXmlApplicationContext的參數:
<allow> ... <create creator="spring" javascript="Fred"> <param name="beanName" value="Shiela"/> <param name="location" value="beans.xml"/> </create> </allow>直接設定BeanFactory
SpringCreator有一個靜態方法 setOverrideBeanFactory(BeanFactory) 用來通過編程的方式直接設定BeanFactory。
配置DWR和Spring
Bram Smeets寫了一個有意思的blog,教你配置DWR使用beans.xml代替WEB-INF/web.xml。
我也對於如何在beans.xml中指定dwr.xml高度興趣,儘管這看上去有些Spring傳染病的感覺。有人知道如何?嗎?請加入郵件清單並告訴大家。
--------------------------------------------------------------------------------
整合
DWR包括兩個JSF的擴充點,一個創造器和一個ServletFilter。
'jsf'創造器
DWR1.1中有一個體驗版的JsfCreator。你可以哉dwr.xml中這樣使用:
<allow> ... <create creator="jsf" javascript="ScriptName"> <param name="managedBeanName" value="beanName"/> <param name="class" value="your.class"/> </create> ...</allow>這將允許你通過DWR調用ManagedBean。
The Servlet Filter
DWR/Faces 過濾器允許你不在JSF的生命週期裡調用FacesContext中的Bean。
要使用JsfCreator,你應該把DWR/Faces過濾器加到web.xml中。
<filter> <filter-name>DwrFacesFilter</filter-name> <filter-class>uk.ltd.getahead.dwr.servlet.FacesExtensionFilter</filter-class></filter><filter-mapping> <filter-name>DwrFacesFilter</filter-name> <url-pattern>/dwr/*</url-pattern></filter-mapping>這兩個需要放在web.xml中與其他的filter和filter-mapping放在一起。
--------------------------------------------------------------------------------
整合Struts
DWR幾乎可以和任何Framework一起工作。這個網站(DWR的官方網站)就是這一點的有力證明,因為它是在Drupal(PHP)中使用DWR。
DWR和Struts整合有兩個層次。最基礎的層次就是同時使用兩個Framework,這是非常容易的,但是這樣就不允許在DWR和Struts之間共用Action了。
DWR可以調用任何方法,所以沒有理由不讓你從DWR調用Struts的Action,除非你不想這樣用。ActionForm的內容是什麼,當返回ActionForward時DWR怎麼做?
一個比較好方法是重構你想調用的Action,提取出Action的邏輯。DWR和你的Action就可以同時調用相同的方法了。
The 'struts' 創造器
DWR1.1增加了一個StrutsCreator。你可以哉dwr.xml中這樣使用:
<allow> ... <create creator="struts" javascript="ScriptName"> <param name="formBean" value="formBeanName"/> </create> ...</allow>這樣就允許你在DWR中調用FormBean了。
開始順序
如果你要使用StrutsCreator那麼你保證Struts在DWR之前被初始化。你可以在web.xml中把Struts的<load-on-startup>設定的比DWR低。
--------------------------------------------------------------------------------
pageflow 創造器
DWR中有一個創造器可以和Weblogic或者Beehive中的PageFlow一起工作。
The 'pageflow' Creator
DWR1.1中加入了一個PageFlowCreator。你可以這樣使用:
<allow> ... <create creator="pageflow" javascript="ScriptName"/> ...</allow>--------------------------------------------------------------------------------使用靜態方法
DWR會在調用建立器之前先檢查一下這個方法是不是靜態,如果是那麼創造器不會被調用。很顯然這個邏輯適用於所有創造器,儘管如此"null"創造器是最容易配置的。適用單例類
對於單例類的建立,最好適用BeanShell和BSF來執行個體化對象。詳細資料參見'Scripted'創造器其他創造器
我麼偶爾也需要一些新的創造器,最常見的是一個EjbCreator。討論新的創造器的好地方是在郵件清單。DWR和HttpSessionBindingListeners
DWR1.x中存貯已經創造的Bean的方法需要注意,它在每次請求時都會調用相同的 setAttribute() 方法。就是說,如果一個Bean在dwr.xml中的聲明周期設定為session,再每次調用bean中的方法時,DWR都會執行一次 session.setAttribute(yourBean) 。這看上去沒有什麼危害,但是如果你要使用servlet的事件機制的,就是說用了HttpSessionBindingListener介面,你就會發現valueBound和valueUnbound事件在每次調用時都會發生,而不是你想像的在bean被建立時以及session到期時。DWR2 只在第一次建立對象時調用 setAttribute() 。 三:Converters
我們必須保證所有的參數都可以被轉換。JDK中的多數類型已經有轉換器了,但是你需要給DWR轉換你的代碼的權利。一般來說JavaBean的參數需要一個<convert ...>定義。預設情況下,如下類型不需要定義就可以轉換:所有的原生類型 boolean,int,double, 等等
原生類型的物件類型 Boolean,Integer,等等
java.lang.String
java.util.Date 和SQL中的Date
以上類型組成的數組
以上類型的集合類型 (Lists, Sets, Maps, Iterators, 等)
從DOM, XOM, JDOM 和 DOM4J中的DOM對象 (類似 Element 和 Document)
下面這些轉換器有單獨章節介紹
Array Converter
Bean and Object Converters
Collection Converter
Enum Converter
DOM Objects
Hibernate整合
Servlet Objects (HttpServletRequest, HttpSession, etc)
基礎的轉換器
原生類型,String,像BigDecimal這樣的簡單對象的轉換器已經有了。你不需要在dwr.xml中<allow>部分的<convert>中定義。它們預設支援。
預設支援的類型包括: boolean, byte, short, int, long, float, double, char, java.lang.Boolean, java.lang.Byte, java.lang.Short, java.lang.Integer, java.lang.Long, java.lang.Float, java.lang.Double, java.lang.Character, java.math.BigInteger, java.math.BigDecimal 和 java.lang.String
Date轉換器
Date轉換器負責在Javascript的Date類型與Java中的Date類型(java.util.Date, java.sql.Date, java.sql.Times or java.sql.Timestamp)之間進行轉換。同基礎的轉換器一樣,DateConverter預設是支援的。
如果你有一個Javascript的字串 (例如"01 Jan 2010") ,你想把它轉換成Java的Date類型有兩個辦法:在javascript中用Date.parse()把它解析成Date類型,然後用DWR的DateConverter傳遞給伺服器;或者把它作為字串傳遞給Server,再用Java中的SimpleDateFormat(或者類似的)來解析。
同樣,如果你有個Java的Date類型並且希望在HTML使用它。你可以先用SimpleDateFormat把它轉換成字串再使用。也可以直接傳Date給Javascript,然後用Javascript格式化。第一種方式簡單一些,儘管浪費了你的轉換器,而且這樣做也會是瀏覽器上的顯示邏輯受到限制。其實後面的方法更好,也有一些工具可以幫你,例如:
The Javascript Toolbox Date formatter
Web Developers Notes on Date formatting
其他對象
其實建立自己的轉換器也很簡單。Converter介面的Javadoc包含了資訊。其實這種需要很少出現。在你寫自己的Converter之前先看看BeanConverter,它有可能就是你要的。
四:<init>
可選的init部分用來聲明創造bean的類和轉換bean的類。多數情況下你不需要用到他們。如果你需要定義一個新的Creator [JavaDoc] 和 Converter [JavaDoc] , 那麼你就需要在這裡定義他們。但是建議你現檢查一下DWR是不是已經支援了。
在init部分裡有了定義只是告訴DWR這些擴充類的存在,給出了如何使用的資訊。這時他們還沒有被使用。這中方式很像Java中的import語句。多數類需要在使用前先import一下,但是只有import語句並不表明這個類已經被使用了。每一個creator和converter都用id屬性,以便後面使用。
五:<signatures>
DWR使用反射來找出在轉換時應該用那種類型。有時類型資訊並不明確,這時你可以在這裡寫下方法的簽名來明確類型。
signatures段使DWR能確定集合中存放的資料類型。例如下面的定義中我們無法知道list中存放的是什麼類型。
public class Check{ public void setLotteryResults(List nos) { ... }}signatures段允許我們暗示DWR應該用什麼類型去處理。格式對以瞭解JDK5的泛型的人來說很容易理解。
<signatures> <![CDATA[ import java.util.List; import com.example.Check; Check.setLotteryResults(List<Integer> nos); ]]></signatures>DWR中又一個解析器專門來做這件事,所以即便你的環境時JDK1.3 DWR也能正常工作。
解析規則基本上會和你預想規則的一樣(有兩個例外),所以java.lang下面的類型會被預設import。
第一個是DWR1.0中解析器的bug,某些環境下不能返回正確類型。所以你也不用管它了。
第二個是這個解析器時"陽光(sunny day)"解析器。就是說它非常寬鬆,不想編譯器那樣嚴格的保證你一定正確。所以有時它也會允許你丟失import:
<signatures> <![CDATA[ import java.util.List; Check.setLotteryResults(List<Integer>); ]]></signatures>將來的DWR版本會使用一個更正式的解析器,這個編譯器會基於官方Java定義,所以你最好不要使用太多這個不嚴格的東西。
signatures段只是用來確定泛型參數中的型別參數。DWR會自己使用反射機制或者運行時類型確定類型,或者假設它是一個String類型。所以:
不需要signatures - 沒有泛型參數:
public void method(String p);public void method(String[] p);需要signatures - DWR不能通過反射確定:
public void method(List<Date> p);public void method(Map<String, WibbleBean> p);不需要signatures - DWR能正確的猜出:
public void method(List<String> p);public void method(Map<String, String> p);不需要signatures - DWR可以通過運行時類型確定:
public List<Date> method(String p);沒有必要讓Javascript中的所有對象的key都是String類型 - 你可以使用其他類型作為key。但是他們在使用之前會被轉換成String類型。DWR1.x用Javascript的特性把key轉換成String。DWR2.0可能會用toString()方法,在服務段進行這一轉換。
六:多個dwr.xml檔案
可以有多個dwr.xml檔案(詳細資料見web.xml文檔)。每個檔案中的定義會被加在一起。DWR用這個功能來載入基礎設定檔。我們可以看看標準被設定檔來瞭解dwr.xml的內容。
以上資源來自http://wiki.javascud.org/display/dwrcn/