Velocity佈局(layout)功能介紹
對於一個WEB應用來說,頁面的基本結構往往是固定的,頁面中的很多部分,例如頁面統一的頭部、尾部和選單,我們一般是不太需要變化的,各個頁面基本一致,變化的往往是頁面的具體內容部分,這樣,佈局(layout)功能的使用,就能大大減化前端頁面的複雜性了。這裡簡單介紹一下如何使用velocity框架來實現頁面的佈局。
我們知道,要在spring框架中配置velocity,一般需要配置兩個bean,一個是velocityConfig,別一個則是viewResolver。先來看velocityConfig的配置,基本配置如下所示,這裡和不使用佈局的配置方式沒有任何差別。
<!-- velocity 配置--><bean id= "velocityConfig" class= "org.springframework.web.servlet.view.velocity.VelocityConfigurer"> <property name= "resourceLoaderPath"> <value>WEB-INF/view</value> </property> <property name= "velocityProperties"> <props> <prop key= "input.encoding">utf-8</prop> <prop key= "output.encoding">utf-8</prop> </props> </property></bean>
接下來看看viewResolver的配置,在使用佈局時,一般會配置如下:
<bean id= "viewResolver"class= "org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver"> <property name= "cache" value= "true"/> <property name= "prefix" value= "/"/> <property name= "suffix" value= ".vm"/> <property name= "contentType"> <value>text/html;charset=utf-8</value> </property> <property name="toolboxConfigLocation"> <value>/WEB-INF/toolbox.xml</value> </property> <property name="layoutUrl" value="layout/layout.vm" /> <property name="allowSessionOverride" value="true"/> <property name="allowRequestOverride" value="true"/> <property name="exposeSessionAttributes" value="true"/> <property name="requestContextAttribute" value="rc"/> <property name="exposeRequestAttributes" value="true"/></bean>
如果你配置過velocity,你會發現與你之前的配置主要有兩個地方的差別:
1. 一般情況下,當我們不使用velocity的佈局功能時,我們一般會把viewResolver的class配置為:
org.springframework.web.servlet.view.velocity.VelocityViewResolver,當需要使用佈局功能的時候,viewResolver的class需要配置為:
org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver,顧名思義,從命名中我們就能看出來這個viewResolver是支援layout功能的。
2. 另外一點不同的是,這裡多了一個layoutUrl的屬性配置:<property name="layoutUrl"value="layout/layout.vm" />, 這個配置是設定你的layout檔案的存在路徑,需要注意的是,這個路徑不是相對於webapp路徑來的,而是相對於velocityConfig配置中的resourceLoaderPath屬性配置的路徑(resourceLoaderPath的路徑是相對於webapp的路徑)。
看看一般情況下,我們的layout頁面大概長什麼樣子吧:
<body> <div class="content"> #parse("/common/header.vm") <div class="content-info"> #parse("/common/leftMenu.vm") <div class="content-main"> $screen_content </div> </div> #parse("common/footer.vm") </div></body>
解釋一下:如果你在處理某個請求時返回了a.vm模板,那麼最終返回的頁面是:將a.vm模板的內容填充layout頁面的$screen_content佔位符的內容,然後再將整個填充後的頁面返回給使用者。如果有興趣你可以看一下大致的實現原理,其實很簡單,就是先呼叫velocity引擎渲染請求返回的模板,將該渲染結果(一個String型別的字串)作為一引數傳遞給layout頁面,引數名稱就是screen_content,然後再次呼叫引擎渲染layout頁面,這樣就會把該screen_content引數對應的值作為頁面的一部分渲染出來了,從而實現整個頁面的佈局功能。
這樣,我們就簡單介紹瞭如何簡單配置和使用velocity的layout功能了,這裡你可以會有疑問了,如果我某個頁面需要使用不同的layout頁面,甚至我有些頁面不需要使用layout功能,該怎麼辦?其實很簡單,我們前面viewResolver配置中,配置的只是預設的layout頁面的地址,如果你要使用不同的layout頁面,只需在你要返回的頁面中如下簡單設定一下即可:
#set($layout = "/layout/layout2.vm")
這樣,我們就強制我們的這個頁面使用的是layout2.vm這個頁面佈局。按照這個思路,如果我在某個特殊的頁面,不想使用layout功能了,我們可以再指定另外一個layout頁面,只不過這個layout頁面內容比較特殊,它沒有一般佈局頁面中有的那些頁面統一的頭部、尾部和選單,只有如下所示的一行程式碼就可以了:
$screen_content
由於暫時沒找到如何在某個頁面中,關閉頁面的layout功能,所以想到了上面的方式投機取巧地實現了類似的功能,如果大家有好的方式可以指出。