我看到的若干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方法,不過根據實際項目經驗,大家都能夠保持習慣,盡量在頁面上不直接調用方法完成業務邏輯。