| 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> 術(shù)語(yǔ)這里是一些必須理解的術(shù)語(yǔ) - 參數會(huì )被converted,遠程Bean會(huì )被created。所以如果你有一個(gè)叫A的bean,它有一個(gè)方法叫A.blah(B) 那么你需要一個(gè)A的creator和一個(gè)B的converter。 一:<allow>allow段落里面定義的試DWR可以創(chuàng )建和轉換的類(lèi)。 二:Creatorsdwr.xml文件中的create元素的結構如下: <allow> <create creator="..." javascript="..." scope="..."> <param name="..." value="..."/> <auth method="..." role="..."/> <exclude method="..."/> <include method="..."/> </create> ...</allow> 這里的多數元素都是可選的 - 你真正必須知道的是指定一個(gè)creator和一個(gè)javascript名字。 creator屬性 是必須的 - 它用來(lái)指定使用那種創(chuàng )造器。 默認情況下DWR1.1有8種創(chuàng )造器。它們是:
如果你需要寫(xiě)自己的創(chuàng )造器,你必須在init部分注冊它。 javascript屬性 用于指定瀏覽器中這個(gè)被創(chuàng )造出來(lái)的對象的名字。你不能使用Javascript的關(guān)鍵字。 scope屬性 非常類(lèi)似servlet規范中的scope。 它允許你指定這個(gè)bean在什么生命范圍。選項有"application", "session", "request" 和"page"。這些值對于Servlet和JSP開(kāi)發(fā)者來(lái)說(shuō)應該相當熟悉了。 scope屬性是可選的。默認是"page"。如果要使用"session"需要cookies。當前的DWR不支持ULR重寫(xiě)。 param元素 被用來(lái)指定創(chuàng )造器的其他參數,每種構造器各有不同。例如,"new"創(chuàng )造器需要知道要創(chuàng )建的對象類(lèi)型是什么。每一個(gè)創(chuàng )造器的參數在各自的文檔中能找到。請查看上面的鏈接。 include和exclude元素 允許創(chuàng )造器來(lái)限制類(lèi)中方法的訪(fǎng)問(wèn)。一個(gè)創(chuàng )造器必須指定include列表或exclude列表之一。如果是include列表則暗示默認的訪(fǎng)問(wèn)策略是"拒絕";如果是exclude列表則暗示默認的訪(fǎng)問(wèn)策略是"允許"。 例如要拒絕防范除了setWibble()以外的所有方法,你應該把如下內容添加到dwr.xml中。 <create creator="new" javascript="Fred"> <param name="class" value="com.example.Fred"/> <include method="setWibble"/></create> 對于加入到create元素中的類(lèi)的所有方法都是默認可見(jiàn)的。 auth元素 允許你指定一個(gè)J2EE的角色作為將來(lái)的訪(fǎng)問(wèn)控制檢查: <create creator="new" javascript="Fred"> <param name="class" value="com.example.Fred"/> <auth method="setWibble" role="admin"/></create> new創(chuàng )造器在DWR中已經(jīng)默認聲明了:<creator id="new" class="uk.ltd.getahead.dwr.create.NewCreator"/> 。你不需要在dwr.xml文件中添加這段話(huà),它已經(jīng)存在于DWR的內部dwr.xml文件中了。 這個(gè)創(chuàng )造器通過(guò)類(lèi)默認的夠早函數創(chuàng )造對象實(shí)例。用new創(chuàng )造器有一些好處:
你可以通過(guò)下面的方式使用new創(chuàng )造器來(lái)創(chuàng )造遠程調用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) 那么一個(gè)新的 java.util.Date 就會(huì )通過(guò)默認的構造函數創(chuàng )造出來(lái), 然后 toString() 方法被調用, 然后結果數據返回給reply方法(在這個(gè)例子中date是字符串格式)。 none'創(chuàng )造器不創(chuàng )建任何對象 - 它會(huì )假設你不需要創(chuàng )建對象。這有可能是對的,有兩個(gè)原因。 你可能在使用的scope不是"page"(看上面),并在在前面已經(jīng)把這個(gè)對象創(chuàng )建到這個(gè)scope中了,這時(shí)你就不需要再創(chuàng )建對象了。 還有一種情況是要調用的方法是靜態(tài)的,這時(shí)也不需要創(chuàng )建對象。DWR會(huì )在調用創(chuàng )建器之前先檢查一下這個(gè)方法是不是靜態(tài)的。 對于上訴兩種情況,你仍然需要class參數,用來(lái)告訴DWR它是在操作的對象類(lèi)型是什么。 scripted創(chuàng )造器在DWR中已經(jīng)默認聲明了:<creator id="script" class="uk.ltd.getahead.dwr.create.ScriptedCreator"/> 這個(gè)創(chuàng )造器用BSF來(lái)執行腳本得到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創(chuàng )造器有如下參數:
需要了解的主題要使用這個(gè)創(chuàng )造器,你需要把一些輔助庫放到WEB-INF/lib文件夾下:BSF的jar包 當 一個(gè)類(lèi)是用script創(chuàng )造出來(lái)的,并且scope是session或application,如果你的腳本改變,session中的類(lèi)和script中 的類(lèi)就不一致了。這樣會(huì )出現錯誤。雖然web容器不用重啟,但是用戶(hù)需要先登出(或以某種方式清空session),然后再登錄。 當clazz參數不為空,并且用來(lái)創(chuàng )造新實(shí)例,DWR簡(jiǎn)單的調用 class.newInstance() 方法。這種方法是沒(méi)問(wèn)題的,除非腳本正在用某個(gè)參數創(chuàng )建一個(gè)類(lèi),或者調用某個(gè)函數來(lái)配置這個(gè)類(lèi)。 不幸的是,每次請求都要重新運行script并造成上面的問(wèn)題。 創(chuàng )造器讓DWR和Spring一起工作的步驟
DWR對于Spring沒(méi)有運行期依賴(lài),所以如果你不使用Spring那么Spring的支持不會(huì )產(chǎn)生任何影響到。 The SpringCreator這個(gè)創(chuàng )造器會(huì )查找spring的中配置的Bean,用Spring去創(chuàng )建它們。如果你已經(jīng)在使用Spring,那么這個(gè)創(chuàng )造器會(huì )非常有用。 你可以通過(guò)下面的方式來(lái)創(chuàng )建遠程調用的Bean: <allow> ... <create creator="spring" javascript="Fred"> <param name="beanName" value="Shiela"/> </create> </allow> 尋找你的Spring配置有三種方式尋找配置文件: ContextLoaderListener最 簡(jiǎn)單的方式是使用org.springframework.web.context.ContextLoaderListener。你不必使用所有的 Spring-MVC功能,只需要這個(gè)Listener就夠了,所以這是個(gè)不錯的方案。你需要在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 指出還有一個(gè)能深入了解ContextLoaderListener 使用location*參數如 果你要在dwr.xml中指定使用哪些bean,你可以使用location*參數。你可以指定任意多個(gè)文件,只要參數以location開(kāi)始并且唯一即 可。例如: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> 直接設置BeanFactorySpringCreator有一個(gè)靜態(tài)方法 setOverrideBeanFactory(BeanFactory) 用來(lái)通過(guò)編程的方式直接設置BeanFactory。 配置DWR和SpringBram Smeets寫(xiě)了一個(gè)有意思的blog 我也對于如何在beans.xml中指定dwr.xml很感興趣,盡管這看上去有些Spring傳染病的感覺(jué)。有人知道如何實(shí)現嗎?請加入郵件列表并告訴大家。 整合DWR包括兩個(gè)JSF的擴展點(diǎn),一個(gè)創(chuàng )造器和一個(gè)ServletFilter。 'jsf'創(chuàng )造器DWR1.1中有一個(gè)體驗版的JsfCreator。你可以哉dwr.xml中這樣使用: <allow> ... <create creator="jsf" javascript="ScriptName"> <param name="managedBeanName" value="beanName"/> <param name="class" value="your.class"/> </create> ...</allow> 這將允許你通過(guò)DWR調用ManagedBean。 The Servlet FilterDWR/Faces 過(guò)濾器允許你不在JSF的生命周期里調用FacesContext中的Bean。 要使用JsfCreator,你應該把DWR/Faces過(guò)濾器加到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> 這兩個(gè)需要放在web.xml中與其他的filter和filter-mapping放在一起。 pageflow 創(chuàng )造器 DWR中有一個(gè)創(chuàng )造器可以和Weblogic或者Beehive中的PageFlow一起工作。 The 'pageflow' CreatorDWR1.1中加入了一個(gè)PageFlowCreator。你可以這樣使用: <allow> ... <create creator="pageflow" javascript="ScriptName"/> ...</allow> 使用靜態(tài)方法DWR會(huì )在調用創(chuàng )建器之前先檢查一下這個(gè)方法是不是靜態(tài)的,如果是那么創(chuàng )造器不會(huì )被調用。很顯然這個(gè)邏輯適用于所有創(chuàng )造器,盡管如此"null"創(chuàng )造器是最容易配置的。 適用單例類(lèi)其他創(chuàng )造器我么偶爾也需要一些新的創(chuàng )造器,最常見(jiàn)的是一個(gè)EjbCreator。討論新的創(chuàng )造器的好地方是在郵件列表 DWR和HttpSessionBindingListenersDWR1.x中存貯已經(jīng)創(chuàng )造的Bean的方法需要注意,它在每次請求時(shí)都會(huì )調用相同的 setAttribute() 方法。就是說(shuō),如果一個(gè)Bean在dwr.xml中的聲明周期設置為session,再每次調用bean中的方法時(shí),DWR都會(huì )執行一次 session.setAttribute(yourBean) 。這看上去沒(méi)有什么危害,但是如果你要使用servlet的事件機制的,就是說(shuō)用了HttpSessionBindingListener接口,你就會(huì )發(fā)現valueBound和valueUnbound事件在每次調用時(shí)都會(huì )發(fā)生,而不是你想像的在bean被創(chuàng )建時(shí)以及session過(guò)期時(shí)。 DWR2 只在第一次創(chuàng )建對象時(shí)調用 setAttribute() 。 三:Converters我們必須保證所有的參數都可以被轉換。JDK中的多數類(lèi)型已經(jīng)有轉換器了,但是你需要給DWR轉換你的代碼的權利。一般來(lái)說(shuō)JavaBean的參數需要一個(gè)<convert ...>定義。 默認情況下,如下類(lèi)型不需要定義就可以轉換:
下面這些轉換器有單獨章節介紹
基礎的轉換器原生類(lèi)型,String,像BigDecimal這樣的簡(jiǎn)單對象的轉換器已經(jīng)有了。你不需要在dwr.xml中<allow>部分的<convert>中定義。它們默認支持。 默 認支持的類(lèi)型包括: 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類(lèi)型與Java中的Date類(lèi)型(java.util.Date, java.sql.Date, java.sql.Times or java.sql.Timestamp)之間進(jìn)行轉換。同基礎的轉換器一樣,DateConverter默認是支持的。 如果你有一個(gè) Javascript的字符串 (例如"01 Jan 2010") ,你想把它轉換成Java的Date類(lèi)型有兩個(gè)辦法:在javascript中用Date.parse()把它解析成Date類(lèi)型,然后用DWR的 DateConverter傳遞給服務(wù)器;或者把它作為字符串傳遞給Server,再用Java中的SimpleDateFormat(或者類(lèi)似的)來(lái)解 析。 同樣,如果你有個(gè)Java的Date類(lèi)型并且希望在HTML使用它。你可以先用SimpleDateFormat把它轉換成字符串再使 用。也可以直接傳Date給Javascript,然后用Javascript格式化。第一種方式簡(jiǎn)單一些,盡管浪費了你的轉換器,而且這樣做也會(huì )是瀏覽 器上的顯示邏輯受到限制。其實(shí)后面的方法更好,也有一些工具可以幫你,例如: 其他對象其實(shí)創(chuàng )建自己的轉換器也很簡(jiǎn)單。Converter接口的Javadoc包含了信息。其實(shí)這種需要很少出現。在你寫(xiě)自己的Converter之前先看看BeanConverter,它有可能就是你要的。 四:<init>可選的init部分用來(lái)聲明創(chuàng )造bean的類(lèi)和轉換bean的類(lèi)。多數情況下你不需要用到他們。如果你需要定義一個(gè)新的Creator [JavaDoc 在init 部分里有了定義只是告訴DWR這些擴展類(lèi)的存在,給出了如何使用的信息。這時(shí)他們還沒(méi)有被使用。這中方式很像Java中的import語(yǔ)句。多數類(lèi)需要在 使用前先import一下,但是只有import語(yǔ)句并不表明這個(gè)類(lèi)已經(jīng)被使用了。每一個(gè)creator和converter都用id屬性,以便后面使 用。 五:<signatures>DWR使用反射來(lái)找出在轉換時(shí)應該用那種類(lèi)型。有時(shí)類(lèi)型信息并不明確,這時(shí)你可以在這里寫(xiě)下方法的簽名來(lái)明確類(lèi)型。 signatures段使DWR能確定集合中存放的數據類(lèi)型。例如下面的定義中我們無(wú)法知道list中存放的是什么類(lèi)型。 public class Check{ public void setLotteryResults(List nos) { ... }} signatures段允許我們暗示DWR應該用什么類(lèi)型去處理。格式對以了解JDK5的泛型的人來(lái)說(shuō)很容易理解。 <signatures> <![CDATA[ import java.util.List; import com.example.Check; Check.setLotteryResults(List<Integer> nos); ]]></signatures> DWR中又一個(gè)解析器專(zhuān)門(mén)來(lái)做這件事,所以即便你的環(huán)境時(shí)JDK1.3 DWR也能正常工作。 解析規則基本上會(huì )和你預想規則的一樣(有兩個(gè)例外),所以java.lang下面的類(lèi)型會(huì )被默認import。 第一個(gè)是DWR1.0中解析器的bug,某些環(huán)境下不能返回正確類(lèi)型。所以你也不用管它了。 第二個(gè)是這個(gè)解析器時(shí)"陽(yáng)光(sunny day)"解析器。就是說(shuō)它非常寬松,不想編譯器那樣嚴格的保證你一定正確。所以有時(shí)它也會(huì )允許你丟失import: <signatures> <![CDATA[ import java.util.List; Check.setLotteryResults(List<Integer>); ]]></signatures> 將來(lái)的DWR版本會(huì )使用一個(gè)更正式的解析器,這個(gè)編譯器會(huì )基于官方Java定義,所以你最好不要使用太多這個(gè)不嚴格的東西。 signatures段只是用來(lái)確定泛型參數中的類(lèi)型參數。DWR會(huì )自己使用反射機制或者運行時(shí)類(lèi)型確定類(lèi)型,或者假設它是一個(gè)String類(lèi)型。所以: 不需要signatures - 沒(méi)有泛型參數: public void method(String p);public void method(String[] p); 需要signatures - DWR不能通過(guò)反射確定: 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可以通過(guò)運行時(shí)類(lèi)型確定: public List<Date> method(String p); 沒(méi) 有必要讓Javascript中的所有對象的key都是String類(lèi)型 - 你可以使用其他類(lèi)型作為key。但是他們在使用之前會(huì )被轉換成String類(lèi)型。DWR1.x用Javascript的特性把key轉換成String。 DWR2.0可能會(huì )用toString()方法,在服務(wù)段進(jìn)行這一轉換。 六:多個(gè)dwr.xml文件可以有多個(gè)dwr.xml文件(詳細信息見(jiàn)web.xml文檔)。每個(gè)文件中的定義會(huì )被加在一起。DWR用這個(gè)功能來(lái)加載基礎配置文件。我們可以看看標準被配置文件來(lái)了解dwr.xml的內容。 |
聯(lián)系客服