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