在以往的應用開發過程中,後端的業務組件(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去創建這樣一個對象。並且做瞭一些初始化工作:
package test;
//imports.
@Component //配置為Spring Bean
@Scope(“view”) //作用域為view
public class SomeAction{
private User user;
private String password;
private UserManager userManager; //自動註入的userManager
@PostConstruct
public void init(){
this.user = this.userManager.get(1);//查找id為1的用戶
}
public void save(){
if(StringUtils.isNotBlank(this.password)){
this.user.setPassword(this.password);
this.userManager.saveOrUpdate(this.user);
}
else
throw new ValidatorException(“Wrong password!”);
}
//getters and setters
Spring創建SomeAction類的一個對象後,會馬上調用init方法,初始化其user屬性。然後頁面展現出來瞭,頁面上你看到瞭用戶名,和密碼輸入框。然後我們填寫一個新的密碼,點擊按鈕提交表單。註意我們的按鈕用的是<a4j:commandButton/>,這個按鈕會采用AJAX的方式提交當前表單。後端JSF接收到這個請求的時候,會調用頁面加載的時候創建的那個SomeAction對象的save方法。於是user對象也正是頁面加載的時候查詢出來的那個user對象。
看到瞭吧,在表單以ajax方式提交的時候,由於SomeAction是view作用域的,所以someAction對象依然是頁面加載時候創建的的那個對象,其中的User屬性也不需要你再次根據請求中的userId去查詢數據庫。
以此類推,我們在一個列表頁面加載的時候,使用一個view作用域的bean作為其action對象,於是加載完成後,要對列表中的某些行執行操作的時候,你都不需要再次去查詢,因為整個對象集合都依然存在!
本質上講,view作用域中的數據時被放在瞭session中。但是JSF實現瞭對於這寫內容的管理方式,不需要使用人員關心。