我看到的若干mvc框架在展現(xiàn)一個(gè)包含動(dòng)態(tài)數(shù)據(jù)內(nèi)容的頁(yè)面的時(shí)候,都是這樣做的:請(qǐng)求/xx.do,到達(dá)某個(gè)action,執(zhí)行配置好或者根據(jù)url映射到的某個(gè)方法,初始化數(shù)據(jù),放到某個(gè)context里面(例如Request,或者struts用的ognl的context),然后根據(jù)配置或者規(guī)則,forward到某頁(yè)面,然后展現(xiàn)。

這樣做的好處是強(qiáng)制性的分離了展現(xiàn)和邏輯,缺點(diǎn)是多了若干配置,不自然。

JSF的路子和asp/php是一樣的,你請(qǐng)求/a.xhtml,那么,ok,加載/a.xhtml文件。例如a.xhtml主體內(nèi)容如下:

<h:form>
        <h:inputText value="#{someAction.txtValue}"/>
        
<h:commandButton action="#{someAction.saveTxtValue}" value="提交"/>
    
</h:form>

當(dāng)頁(yè)面加載,走到#{someAction.txtValue}這個(gè)表達(dá)式的時(shí)候, 表達(dá)式解析器會(huì)去找spring要一個(gè)名字為someAction的bean。spring發(fā)現(xiàn)自己沒有創(chuàng)建過這樣的一個(gè)bean。根據(jù)bean的定義,于是創(chuàng)建了這樣一個(gè)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現(xiàn)在已經(jīng)被設(shè)置到了this.txtValue上
        }
        
//getters and setters
    }

這個(gè)類里面的全部?jī)?nèi)容和JSF的技術(shù)細(xì)節(jié)沒有任何關(guān)系,只是一個(gè)簡(jiǎn)單的spring bean。

顯然spring創(chuàng)建這個(gè)bean之后會(huì)調(diào)用標(biāo)注了PostConstruct注解的方法,這里我們做數(shù)據(jù)初始化工作。接下來繼續(xù)頁(yè)面加載過程,于是會(huì)展現(xiàn)出來一個(gè)輸入框,值是the beginning.

這樣做其實(shí)技術(shù)上允許你在頁(yè)面上寫邏輯調(diào)用了,例如直接在頁(yè)面上寫個(gè)#{someAction.xx()},頁(yè)面加載的時(shí)候就會(huì)調(diào)用這個(gè)xx方法,不過根據(jù)實(shí)際項(xiàng)目經(jīng)驗(yàn),大家都能夠保持習(xí)慣,盡量在頁(yè)面上不直接調(diào)用方法完成業(yè)務(wù)邏輯。