在以往的應用開發過程中,后端的業務組件(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實現了對于這寫內容的管理方式,不需要使用人員關心。