背景: 在使用struts時我們經(jīng)常會用到DispatchAction.有了這個類,我們不需要針對每一個Action都要寫一個特定的類,而是可以把一些相關(guān)的方法放到一個類中. DispatchActon中使用了reflection來根據(jù)你傳入的method參數(shù)的值來獲取相應(yīng)的參數(shù)來處理你的請求.正如他的方法 -- 他根據(jù)你傳入的請求參數(shù),用不同的方法來處理你的請求. 但是,通常我們還會遇到另一種情況,如果我想在之行實際的action處理方法之前或者之后再去做一些別的事情而又不想修改我們實際存在的action類呢?這里我將介紹一種方法. 只要看看struts中DispatchAction(以下簡寫做DA)的源文件你就會發(fā)現(xiàn),它有一個dispatchMethod方法,接受5個參數(shù).其中4個就是我們通常的struts action里的(mapping,request,response,form),還有一個參數(shù)就是指定方法的參數(shù)的名字. protected ActionForward dispatchMethod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String name) throws Exception 其實現(xiàn)方法如下: // Make sure we have a valid method name to call. // This may be null if the user hacks the query string. if (name == null) { return this.unspecified(mapping, form, request, response); } // Identify the method object to be dispatched to Method method = null; try { method = getMethod(name); } catch (NoSuchMethodException e) { String message = messages.getMessage("dispatch.method", mapping .getPath(), name); log.error(message, e); throw e; } ActionForward forward = null; try { Object args[] = { mapping, form, request, response }; //特殊的url不進行處理(add) String actionUrl = request.getServletPath(); // "/rolesign.do" boolean exception = isException(actionUrl); if(exception) { logger.debug("requestUrl :"+actionUrl+",no pre and post process"); } // 預(yù)處理(add) if (!disabled && !exception) { logger.debug("preProcess begin"); preProcess(request); logger.debug("preProcess end"); } forward = (ActionForward) method.invoke(this, args); // 后處理(add) if (!disabled && !exception ){ logger.debug("postProcess begin"); postProcess(request); logger.debug("postProcess end"); } } catch (ClassCastException e) { String message = messages.getMessage("dispatch.return", mapping .getPath(), name); log.error(message, e); throw e; } catch (IllegalAccessException e) { String message = messages.getMessage("dispatch.error", mapping .getPath(), name); log.error(message, e); throw e; } catch (InvocationTargetException e) { // Rethrow the target exception if possible so that the // exception handling machinery can deal with it Throwable t = e.getTargetException(); if (t instanceof Exception) { throw ((Exception) t); } else { String message = messages.getMessage("dispatch.error", mapping .getPath(), name); log.error(message, e); throw new ServletException(t); } } // Return the returned ActionForward instance return (forward); 大部分代碼還是從DA的實現(xiàn)方法中copy過來,但是我在這里加入了3個地方.分別是: 1.對請求url的識別,確定是否使用預(yù)/后處理 2.預(yù)處理方法調(diào)用 3.后處理方法調(diào)用 當(dāng)然你要自己寫預(yù)處理方法和后處理方法.這里你可以傳任意你想要的參數(shù)給request,然后通過reflection來動態(tài)調(diào)用任意的java方法,比如你可以在頁面設(shè)置一個preFunction參數(shù),它的值是classname.methodname.然后你可以在preProcess的實現(xiàn)中通過reflection來查找這個方法并執(zhí)行. 如果你想讓項目中所有的action都有這種特性,則只要讓根Action繼承DA并覆蓋它的dispatchMethod方法即可. 這是在實際項目中用到的一個特性,為了盡可能少的修改原有的代碼使用了這種折中的做法.使用reflection時建議不要執(zhí)行太過復(fù)雜的方法,可能會使你的action響應(yīng)慢的. |
|