我看到的若干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方法,不过根据实际项目经验,大家都能够保持习惯,尽量在页面上不直接调用方法完成业务逻辑。