久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

2.5.3使用 paramsPrepareParamsStack 攔截器棧后的運行流程

 liumw1203 2015-03-07
1). paramsPrepareParamsStack 和 defaultStack 一樣都是攔截器棧. 而 struts-default 包默認使用的是
defaultStack

2). 可以在 Struts 配置文件中通過以下方式修改使用的默認的攔截器棧

<default-interceptor-ref name="paramsPrepareParamsStack"></default-interceptor-ref>

3). paramsPrepareParamsStack 攔截器在于

params -> modelDriven -> params

所以可以先把請求參數(shù)賦給 Action 對應(yīng)的屬性, 再根據(jù)賦給 Action 的那個屬性值決定壓到值棧棧頂?shù)膶ο? 最后再為棧頂對象的屬性賦值.

對于 edit 操作而言:

I.   先為 EmployeeAction 的 employeeId 賦值
II.  根據(jù) employeeId 從數(shù)據(jù)庫中加載對應(yīng)的對象, 并放入到值棧的棧頂
III. 再為棧頂對象的 employeeId 賦值(實際上此時 employeeId 屬性值已經(jīng)存在)
IV.  把棧頂對象的屬性回顯在表單中.

4). 關(guān)于回顯: Struts2 表單標簽會從值棧中獲取對應(yīng)的屬性值進行回顯. 

5). 存在的問題: 

getModel 方法

public Employee getModel() {
if(employeeId == null)
employee = new Employee();
else
employee = dao.get(employeeId);
return employee;
}

I.   在執(zhí)行刪除的時候, employeeId 不為 null, 但 getModel 方法卻從數(shù)據(jù)庫加載了一個對象. 不該加載!
II.  指向查詢?nèi)啃畔r, 也 new Employee() 對象. 浪費!

6). 解決方案: 使用 PrepareInterceptor 和 Preparable 接口. 

7). 關(guān)于 PrepareInterceptor

[分析后得到的結(jié)論]
 
若 Action 實現(xiàn)了 Preparable 接口, 則 Struts 將嘗試執(zhí)行 prepare[ActionMethodName] 方法,
若 prepare[ActionMethodName] 不存在, 則將嘗試執(zhí)行 prepareDo[ActionMethodName] 方法.
若都不存在, 就都不執(zhí)行.

若 PrepareInterceptor  的 alwaysInvokePrepare 屬性為 false, 
則 Struts2 將不會調(diào)用實現(xiàn)了 Preparable 接口的  Action 的 prepare() 方法

[能解決 5) 的問題的方案]

可以為每一個 ActionMethod 準備 prepare[ActionMethdName] 方法, 而拋棄掉原來的 prepare() 方法
將 PrepareInterceptor  的 alwaysInvokePrepare 屬性置為 false, 以避免 Struts2 框架再調(diào)用 prepare() 方法.

如何在配置文件中為攔截器棧的屬性賦值: 參看 /struts-2.3.15.3/docs/WW/docs/interceptors.html

<interceptors>
    <interceptor-stack name="parentStack">
        <interceptor-ref name="defaultStack">
            <param name="params.excludeParams">token</param>
        </interceptor-ref>
    </interceptor-stack>
</interceptors>
 
<default-interceptor-ref name="parentStack"/>

----------------------------------源代碼解析---------------------------------

public String doIntercept(ActionInvocation invocation) throws Exception {
//獲取 Action 實例
    Object action = invocation.getAction();

//判斷 Action 是否實現(xiàn)了 Preparable 接口
    if (action instanceof Preparable) {
        try {
            String[] prefixes;
            //根據(jù)當前攔截器的 firstCallPrepareDo(默認為 false) 屬性確定 prefixes
            if (firstCallPrepareDo) {
                prefixes = new String[] {ALT_PREPARE_PREFIX, PREPARE_PREFIX};
            } else {
                prefixes = new String[] {PREPARE_PREFIX, ALT_PREPARE_PREFIX};
            }
            //若為 false, 則 prefixes: prepare, prepareDo
            //調(diào)用前綴方法.
            PrefixMethodInvocationUtil.invokePrefixMethod(invocation, prefixes);
        }
        catch (InvocationTargetException e) {

            Throwable cause = e.getCause();
            if (cause instanceof Exception) {
                throw (Exception) cause;
            } else if(cause instanceof Error) {
                throw (Error) cause;
            } else {
                throw e;
            }
        }

//根據(jù)當前攔截器的 alwaysInvokePrepare(默認是 true) 決定是否調(diào)用 Action 的 prepare 方法
        if (alwaysInvokePrepare) {
            ((Preparable) action).prepare();
        }
    }

    return invocation.invoke();
}

PrefixMethodInvocationUtil.invokePrefixMethod(invocation, prefixes) 方法: 

public static void invokePrefixMethod(ActionInvocation actionInvocation, String[] prefixes) throws InvocationTargetException, IllegalAccessException {
//獲取 Action 實例
Object action = actionInvocation.getAction();
//獲取要調(diào)用的 Action 方法的名字(update)
String methodName = actionInvocation.getProxy().getMethod();
if (methodName == null) {
// if null returns (possible according to the docs), use the default execute 
        methodName = DEFAULT_INVOCATION_METHODNAME;
}
//獲取前綴方法
Method method = getPrefixedMethod(prefixes, methodName, action);
//若方法不為 null, 則通過反射調(diào)用前綴方法
if (method != null) {
method.invoke(action, new Object[0]);
}
}

PrefixMethodInvocationUtil.getPrefixedMethod 方法: 

public static Method getPrefixedMethod(String[] prefixes, String methodName, Object action) {
assert(prefixes != null);
//把方法的首字母變?yōu)榇髮?/div>
String capitalizedMethodName = capitalizeMethodName(methodName);
    
    //遍歷前綴數(shù)組
    for (String prefixe : prefixes) {
        //通過拼接的方式, 得到前綴方法名: 第一次 prepareUpdate, 第二次 prepareDoUpdate
        String prefixedMethodName = prefixe + capitalizedMethodName;
        try {
        //利用反射獲從 action 中獲取對應(yīng)的方法, 若有直接返回. 并結(jié)束循環(huán).
            return action.getClass().getMethod(prefixedMethodName, EMPTY_CLASS_ARRAY);
        }
        catch (NoSuchMethodException e) {
            // hmm -- OK, try next prefix
            if (LOG.isDebugEnabled()) {
                LOG.debug("cannot find method [#0] in action [#1]", prefixedMethodName, action.toString());
            }
        }
    }
return null;
}

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導購買等信息,,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多