在以往的應用開發過程中,后端的業務組件(Action/Service/Dao),可以被設置為幾種作用域:request、session、application。我們不可能把與每次請求關系很強的一些信息(例如某個列表頁面要列出來的數據集合)簡單的放到session里面去,這就導致了每次請求之間的大部分數據是不可能共享的。使用JSF,我們實現了一種叫做view的作用域,在不同的請求之間共享信息。
新版的spring中提出了一個conversation作用于,也是介于request和session之間的一個作用于,和seam中的conversation應該差不多。
view作用域是生命周期介于request和session之間的一個作用范圍。當一個Spring Bean(一般來說是Action層面的Bean)被標注作用域為view的時候,Spring會在需要用到這個Bean的時候創建之,然后,在當前頁面沒有發生整頁的reload、跳轉的情況下,這個bean一直存在。所謂整頁reload、跳轉說的就是我們普通的表單提交,URL GET請求。發生除此之外的其他請求(目前能想到的其實也就是一種:Ajax請求)的時候,前面創建出來的bean對象一直存在。看一個具體的例子,首先是頁面:
<!-- some.xhtml -->
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:a4j="http://richfaces.org/a4j">
<h:form>
用戶名:<h:outputText value="#{someAction.user.username}"/><br/>
新密碼:<h:inputSecret value="#{someAction.password}"/><br/>
<a4j:commandButton value="修改密碼" action="#{someAction.save}"/>
</h:form>
</html>
這個頁面實現修改一個用戶的密碼,當我們請求這個頁面的時候,JSF發現你要使用someAction這個對象,所以他會告訴Spring去創建這樣一個對象。并且做了一些初始化工作:
Spring創建SomeAction類的一個對象后,會馬上調用init方法,初始化其user屬性。然后頁面展現出來了,頁面上你看到了用戶名,和密碼輸入框。然后我們填寫一個新的密碼,點擊按鈕提交表單。注意我們的按鈕用的是<a4j:commandButton/>,這個按鈕會采用AJAX的方式提交當前表單。后端JSF接收到這個請求的時候,會調用頁面加載的時候創建的那個SomeAction對象的save方法。于是user對象也正是頁面加載的時候查詢出來的那個user對象。
看到了吧,在表單以ajax方式提交的時候,由于SomeAction是view作用域的,所以someAction對象依然是頁面加載時候創建的的那個對象,其中的User屬性也不需要你再次根據請求中的userId去查詢數據庫。
以此類推,我們在一個列表頁面加載的時候,使用一個view作用域的bean作為其action對象,于是加載完成后,要對列表中的某些行執行操作的時候,你都不需要再次去查詢,因為整個對象集合都依然存在!
本質上講,view作用域中的數據時被放在了session中。但是JSF實現了對于這寫內容的管理方式,不需要使用人員關心。