在以往的应用开发过程中,后端的业务组件(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实现了对于这写内容的管理方式,不需要使用人员关心。