我看到的若干mvc框架在展现一个包含动态数据内容的页面的时候,都是这样做的:请求/xx.do,到达某个action,执行配置好或者根据url映射到的某个方法,初始化数据,放到某个context里面(例如Request,或者struts用的ognl的context),然后根据配置或者规则,forward到某页面,然后展现。
这样做的好处是强制性的分离了展现和逻辑,缺点是多了若干配置,不自然。
JSF的路子和asp/php是一样的,你请求/a.xhtml,那么,ok,加载/a.xhtml文件。例如a.xhtml主体内容如下:
<h:form>
<h:inputText value="#{someAction.txtValue}"/>
<h:commandButton action="#{someAction.saveTxtValue}" value="提交"/>
</h:form>
当页面加载,走到#{someAction.txtValue}这个表达式的时候, 表达式解析器会去找spring要一个名字为someAction的bean。spring发现自己没有创建过这样的一个bean。根据bean的定义,于是创建了这样一个bean。该类定义如下:
@Component("someAction")
@Scope("request")
public class SomeAction{
private String txtValue;
@PostConstruct
public void init(){
this.txtValue = "the beginning";
}
public void saveTxtValue(){
//do sth.
//用户输入的txtValue现在已经被设置到了this.txtValue上
}
//getters and setters
}
这个类里面的全部内容和JSF的技术细节没有任何关系,只是一个简单的spring bean。
显然spring创建这个bean之后会调用标注了PostConstruct注解的方法,这里我们做数据初始化工作。接下来继续页面加载过程,于是会展现出来一个输入框,值是the beginning.
这样做其实技术上允许你在页面上写逻辑调用了,例如直接在页面上写个#{someAction.xx()},页面加载的时候就会调用这个xx方法,不过根据实际项目经验,大家都能够保持习惯,尽量在页面上不直接调用方法完成业务逻辑。