Struts2 的ModelDriven 二——ModelDrive

 

繼上篇博客介紹了值傳遞的幾種形式,這篇博客,來講說struts2是如何實現的? 
有這麼兩個概念和modelDriven實現有關:ValueStack,ModelDrivenInterceptor。html

1、ModelDrivenInterceptor

首先先介紹如下ModelDrivenInterceptor,該攔截器處於defaultStack第九的位置。ModelDrivenInterceptor攔截器主要作的事就是調用Action的getModel()方法而後把返回的model壓入值棧。 
下面是該攔截器intercept方法源碼:java

public class ModelDrivenInterceptor extends AbstractInterceptor {
    protected boolean refreshModelBeforeResult = false;

    public void setRefreshModelBeforeResult(boolean val) {
        this.refreshModelBeforeResult = val;
    } 
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        Object action = invocation.getAction();

        if (action instanceof ModelDriven) {
            ModelDriven modelDriven = (ModelDriven) action;
            ValueStack stack = invocation.getStack();
            Object model = modelDriven.getModel();
            if (model !=  null) {
              stack.push(model);
            }
            if (refreshModelBeforeResult) {
                invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
            }
        }
        return invocation.invoke();
    }

此方法就是就是把getModel方法返回的結果壓入值棧而已,咱們通常實現這個接口是利用壓入值棧的model對象接收從頁面提交過來的數據,由於Action也是在值棧中,而struts2在賦值參數的時候是在值棧從棧頂往棧底尋找有相應setter方法的對象,而這時model壓入了值棧,它是處於棧頂的,因此從頁面提交過來的參數也就被model對象接收了。服務器

2、ValueStack

這個ValueStack和 struts的ognl是分不開的。(valueStack是接口,ognl實現了該接口) 
ValueStack實際上就是對OGNL的封裝,OGNL主要的功能就是賦值與取值,Struts2正是經過ValueStack來進行賦值與取值的!ide

ValueStack是一個接口,而OgnlValueStack是strtus2中的缺省實現。ValueStack中的數據,分兩個部分存放:root和context(這與OGNL中的概念一致),同時ValueStack暴露相關的接口:this

void setValue(String expr, Object value);spa

Object findValue(String expr);.net

用來經過OGNL表達式對ValueStack中的數據進行操做!code

ValueStack中的root對象是CompoundRoot,CompoundRoot繼承了ArraryList,提供了額外的方法:push()和pop()方法,用來對root對象中所包含的數據進行存取!htm

public class CompoundRoot extends ArrayList { 
    public CompoundRoot() {
    }
    public CompoundRoot(List list) {
        super(list);
    }
    public CompoundRoot cutStack(int index) {
        return new CompoundRoot(subList(index, size()));
    }
    public Object peek() {
        return get(0);
    }
    public Object pop() {
        return remove(0);
    }
    public void push(Object o) {
        add(0, o);
    }
}

 

正是經過這兩個方法,CompoundRoot變成了一個棧結構!壓棧操做,將致使對象被放到CompoundRoot的第0個元素上(第0個元素 是棧頂),其它對象被依次日後移動;出棧操做,將致使CompoundRoot的第0個元素被移除(即棧頂元素被彈出),其它對象被依次往前移動!對象

OGNL不支持多個root對象,而struts2可以支持多個root對象,它對OGNL作了擴展。

若是某個OGNL表達式被傳遞給ValueStack(即調用ValueStack的setValue或findValue方法),而表達式中包含 有對root對象的訪問操做,ValueStack將依次從棧頂往棧底搜索CompoundRoot對象中所包含的對象,看哪一個對象具備相應的屬性,找到 以後,馬上返回。

3、存與 取 的實現

這裏的存是:客戶端請求中的參數如何被 「存」 進 ValueStack,例如:添加操做;而 「取」 是指服務器查詢數據,如何回顯到前臺頁面,例如 更新操做。 
接下來,咱們看 存 的實現,其實就是博客開篇提到的,三種方法,一個原則:前臺 控件的name必須是和實體屬性名稱是一致的。這裏再也不贅述。 
主要是看 「取」 的實現。 
服務器端,咱們須要手動將model 壓入 ValueStack:ActionContext.getContext().getValueStack().push(××);

public class UserAction
     {
    //查看用戶的詳細信息
    public String detail()
    {
       User u = new User();
       u.setUsername("wyx");
       ActionContext.getContext().getValueStack().push(u);
       return "update";
        }
}

在JSP中: 對應的JSP使用 struts2標籤 + ognl 來取。

username:<input type="text" name="username" value="<s:property value="username"/>"> <br/>

或者:

<s:textfield name="username"/>

總結

因此struts2的modelDriven機制:  一、客戶端請求:當一個請求過來,首先被modelDriveInterceptor攔截,執行getModel方法,壓入valueStack,ValueStack 將請求的值和壓入的model進行對比賦值;  二、服務端回發:咱們須要把model push進ValueStack。前臺使用 struts2標籤 + ognl來接受,解析。

相關文章
相關標籤/搜索