在以往的應(yīng)用開發(fā)過程中,后端的業(yè)務(wù)組件(Action/Service/Dao),可以被設(shè)置為幾種作用域:request、session、application。我們不可能把與每次請(qǐng)求關(guān)系很強(qiáng)的一些信息(例如某個(gè)列表頁面要列出來的數(shù)據(jù)集合)簡(jiǎn)單的放到session里面去,這就導(dǎo)致了每次請(qǐng)求之間的大部分?jǐn)?shù)據(jù)是不可能共享的。使用JSF,我們實(shí)現(xiàn)了一種叫做view的作用域,在不同的請(qǐng)求之間共享信息。


新版的spring中提出了一個(gè)conversation作用于,也是介于request和session之間的一個(gè)作用于,和seam中的conversation應(yīng)該差不多。


view作用域是生命周期介于request和session之間的一個(gè)作用范圍。當(dāng)一個(gè)Spring Bean(一般來說是Action層面的Bean)被標(biāo)注作用域?yàn)関iew的時(shí)候,Spring會(huì)在需要用到這個(gè)Bean的時(shí)候創(chuàng)建之,然后,在當(dāng)前頁面沒有發(fā)生整頁的reload、跳轉(zhuǎn)的情況下,這個(gè)bean一直存在。所謂整頁reload、跳轉(zhuǎn)說的就是我們普通的表單提交,URL GET請(qǐng)求。發(fā)生除此之外的其他請(qǐng)求(目前能想到的其實(shí)也就是一種:Ajax請(qǐng)求)的時(shí)候,前面創(chuàng)建出來的bean對(duì)象一直存在。看一個(gè)具體的例子,首先是頁面:


 <!-- 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>


這個(gè)頁面實(shí)現(xiàn)修改一個(gè)用戶的密碼,當(dāng)我們請(qǐng)求這個(gè)頁面的時(shí)候,JSF發(fā)現(xiàn)你要使用someAction這個(gè)對(duì)象,所以他會(huì)告訴Spring去創(chuàng)建這樣一個(gè)對(duì)象。并且做了一些初始化工作:



package test; 
//imports.  
@Component        //配置為Spring Bean 
@Scope("view")    //作用域?yàn)関iew 
public class SomeAction{ 
    
private User user; 
    
private String password; 
    
private UserManager userManager;    //自動(dòng)注入的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創(chuàng)建SomeAction類的一個(gè)對(duì)象后,會(huì)馬上調(diào)用init方法,初始化其user屬性。然后頁面展現(xiàn)出來了,頁面上你看到了用戶名,和密碼輸入框。然后我們填寫一個(gè)新的密碼,點(diǎn)擊按鈕提交表單。注意我們的按鈕用的是<a4j:commandButton/>,這個(gè)按鈕會(huì)采用AJAX的方式提交當(dāng)前表單。后端JSF接收到這個(gè)請(qǐng)求的時(shí)候,會(huì)調(diào)用頁面加載的時(shí)候創(chuàng)建的那個(gè)SomeAction對(duì)象的save方法。于是user對(duì)象也正是頁面加載的時(shí)候查詢出來的那個(gè)user對(duì)象。


看到了吧,在表單以ajax方式提交的時(shí)候,由于SomeAction是view作用域的,所以someAction對(duì)象依然是頁面加載時(shí)候創(chuàng)建的的那個(gè)對(duì)象,其中的User屬性也不需要你再次根據(jù)請(qǐng)求中的userId去查詢數(shù)據(jù)庫(kù)。

以此類推,我們?cè)谝粋€(gè)列表頁面加載的時(shí)候,使用一個(gè)view作用域的bean作為其action對(duì)象,于是加載完成后,要對(duì)列表中的某些行執(zhí)行操作的時(shí)候,你都不需要再次去查詢,因?yàn)檎麄€(gè)對(duì)象集合都依然存在!


本質(zhì)上講,view作用域中的數(shù)據(jù)時(shí)被放在了session中。但是JSF實(shí)現(xiàn)了對(duì)于這寫內(nèi)容的管理方式,不需要使用人員關(guān)心。