您好,登錄后才能下訂單哦!
這篇文章主要介紹Struts2源碼分析之ParametersInterceptor攔截器怎么用,文中介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們一定要看完!
前言
ParametersInterceptor攔截器其主要功能是把ActionContext中的請求參數(shù)設(shè)置到ValueStack中,如果棧頂是當(dāng)前Action則把請求參數(shù)設(shè)置到了Action中,如果棧頂是一個model(Action實現(xiàn)了ModelDriven接口)則把參數(shù)設(shè)置到了model中。
下面是該攔截器的doIntercept方法源碼:
@Override public String doIntercept(ActionInvocation invocation) throws Exception { Object action = invocation.getAction();//獲取當(dāng)前執(zhí)行的Action對象 if (!(action instanceof NoParameters)) {//判斷Action是否實現(xiàn)了NoParameters接口,實現(xiàn)該接口表示該Action沒有任何請求參數(shù) ActionContext ac = invocation.getInvocationContext();//獲取ActionContext對象 final Map<String, Object> parameters = retrieveParameters(ac);//獲取請求參數(shù)Map //省略... if (parameters != null) {//如果請求參數(shù)不為null Map<String, Object> contextMap = ac.getContextMap();//獲取ActionContext內(nèi)部的context Map,即OgnlContext對象 try { //省略... ValueStack stack = ac.getValueStack();//獲取值棧 setParameters(action, stack, parameters);//為值棧設(shè)置參數(shù) } finally { //省略... } } } return invocation.invoke();//調(diào)用下一個攔截器 }
setParameters方法才是該攔截器的主要邏輯,現(xiàn)在進(jìn)入該方法:
protected void setParameters(Object action, ValueStack stack, final Map<String, Object> parameters) { ParameterNameAware parameterNameAware = (action instanceof ParameterNameAware) ? (ParameterNameAware) action : null;//判斷Action有無實現(xiàn)ParameterNameAware接口 Map<String, Object> params; Map<String, Object> acceptableParameters;//合法參數(shù)集合 //判斷參數(shù)設(shè)置是否有序,ordered默認(rèn)為false,即無序 if (ordered) { params = new TreeMap<String, Object>(getOrderedComparator());//如果有序則要獲取比較器 acceptableParameters = new TreeMap<String, Object>(getOrderedComparator()); params.putAll(parameters); } else { params = new TreeMap<String, Object>(parameters); acceptableParameters = new TreeMap<String, Object>(); } //迭代請求參數(shù) for (Map.Entry<String, Object> entry : params.entrySet()) { String name = entry.getKey(); //判斷參數(shù)是否合法,如果Action實現(xiàn)了ParameterNameAware則acceptableName(name)返回true且parameterNameAware.acceptableParameterName(name) //也返回true該參數(shù)才是合法的;如果Action沒有實現(xiàn)ParameterNameAware則參數(shù)是否合法由acceptableName(name)方法決定 boolean acceptableName = acceptableName(name) && (parameterNameAware == null || parameterNameAware.acceptableParameterName(name)); //如果參數(shù)合法 if (acceptableName) { acceptableParameters.put(name, entry.getValue());//把合法參數(shù)添加到合法參數(shù)集合中 } } ValueStack newStack = valueStackFactory.createValueStack(stack); //省略... for (Map.Entry<String, Object> entry : acceptableParameters.entrySet()) {//迭代合法參數(shù) String name = entry.getKey();//參數(shù)名 Object value = entry.getValue();//參數(shù)值 try { newStack.setValue(name, value);//將該參數(shù)設(shè)置到ValueStack中 } catch (RuntimeException e) { //省略... } } //省略... //看該方法的名稱是將合法參數(shù)添加到ActionContext中,但在該攔截器中,該方法為空實現(xiàn),無任何代碼 //該方法被聲明為protected,即子類可以覆蓋該方法以改變行為 addParametersToContext(ActionContext.getContext(), acceptableParameters); }
根據(jù)上面的注釋大家應(yīng)該可以發(fā)現(xiàn)該setParameters方法邏輯還是很明確的,就是先判斷提交過來的參數(shù)是否合法,因為提交過來的參數(shù)會影響到值棧所以struts2要對提交過來的參數(shù)進(jìn)行合法性檢查,以防止惡意用戶的攻擊,凡是請求參數(shù)中表達(dá)式中含有等號(=),逗號(,),#號(#)的都是非法表達(dá)式,現(xiàn)在就去看一下具體是如何判斷一個參數(shù)是否合法的。
上面注釋也講到了,如果Action實現(xiàn)了ParameterNameAware,即要判斷ParameterNameAware接口中聲明的acceptableParameterName(name)方法(邏輯由自己實現(xiàn))也要判斷該攔截器的acceptableName(name)方法,我們這里假設(shè)Action沒有實現(xiàn)ParameterNameAware接口,參數(shù)是否合法由acceptableName(name)方法決定,下面是該方法源碼:
protected boolean acceptableName(String name) { //調(diào)用isAccepted與isExcluded方法判斷 if (isAccepted(name) && !isExcluded(name)) { return true; } return false; }
isAccepted與isExcluded方法源碼:
protected boolean isAccepted(String paramName) { if (!this.acceptParams.isEmpty()) { for (Pattern pattern : acceptParams) { Matcher matcher = pattern.matcher(paramName); if (matcher.matches()) { return true; } } return false; } else return acceptedPattern.matcher(paramName).matches(); } protected boolean isExcluded(String paramName) { if (!this.excludeParams.isEmpty()) { for (Pattern pattern : excludeParams) { Matcher matcher = pattern.matcher(paramName); if (matcher.matches()) { return true; } } } return false; }
上面說到了該攔截器配置了參數(shù)過濾,配置了一個名為excludeParams的參數(shù),用于指定哪些參數(shù)要排除,即不合法,我們傳遞的時候是字符串在設(shè)置該字符串的時候該攔截器會對該字符串進(jìn)行解析轉(zhuǎn)化成相應(yīng)的Pattern對象以用于正則表達(dá)式校驗,而isAccepted與isExcluded方法中就是在用這些正則表達(dá)式進(jìn)行檢驗,邏輯很簡單,就說這么多。
最終進(jìn)行參數(shù)賦值是調(diào)用的ValueStack的setValue方法,該方法內(nèi)部使用是OGNL表達(dá)式引擎進(jìn)行賦值的,雖然內(nèi)部非常復(fù)雜,但我們只需要知道OGNL表達(dá)式引擎在把請求參數(shù)設(shè)置到ValueStack中時,是從棧頂往棧底尋找有相應(yīng)setter方法的對象,如果正在賦值的參數(shù)在ValueStack找到了一個對象有setter方法則把該參數(shù)的值賦給該對象,如果沒有找到則繼承往棧底尋找,直到找到為止,如果找到棧底還是沒有找到也就沒有賦值成功。
以上是“Struts2源碼分析之ParametersInterceptor攔截器怎么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。