欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Struts2源碼分析之ParametersInterceptor攔截器

 更新時(shí)間:2019年06月18日 11:54:49   作者:chen_hao  
這篇文章主要介紹了Struts2源碼分析之ParametersInterceptor攔截器,ParametersInterceptor攔截器其主要功能是把ActionContext中的請求參數(shù)設(shè)置到ValueStack中,,需要的朋友可以參考下

前言

ParametersInterceptor攔截器其主要功能是把ActionContext中的請求參數(shù)設(shè)置到ValueStack中,如果棧頂是當(dāng)前Action則把請求參數(shù)設(shè)置到了Action中,如果棧頂是一個(gè)model(Action實(shí)現(xiàn)了ModelDriven接口)則把參數(shù)設(shè)置到了model中。

下面是該攔截器的doIntercept方法源碼:

@Override
public String doIntercept(ActionInvocation invocation) throws Exception {
Object action = invocation.getAction();//獲取當(dāng)前執(zhí)行的Action對(duì)象
if (!(action instanceof NoParameters)) {//判斷Action是否實(shí)現(xiàn)了NoParameters接口,實(shí)現(xiàn)該接口表示該Action沒有任何請求參數(shù)
ActionContext ac = invocation.getInvocationContext();//獲取ActionContext對(duì)象
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對(duì)象
try {
//省略...
ValueStack stack = ac.getValueStack();//獲取值棧
setParameters(action, stack, parameters);//為值棧設(shè)置參數(shù)
} finally {
//省略...
}
}
}
return invocation.invoke();//調(diào)用下一個(gè)攔截器
}

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有無實(shí)現(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實(shí)現(xiàn)了ParameterNameAware則acceptableName(name)返回true且parameterNameAware.acceptableParameterName(name)
//也返回true該參數(shù)才是合法的;如果Action沒有實(shí)現(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中,但在該攔截器中,該方法為空實(shí)現(xiàn),無任何代碼
//該方法被聲明為protected,即子類可以覆蓋該方法以改變行為
addParametersToContext(ActionContext.getContext(), acceptableParameters);
}

根據(jù)上面的注釋大家應(yīng)該可以發(fā)現(xiàn)該setParameters方法邏輯還是很明確的,就是先判斷提交過來的參數(shù)是否合法,因?yàn)樘峤贿^來的參數(shù)會(huì)影響到值棧所以struts2要對(duì)提交過來的參數(shù)進(jìn)行合法性檢查,以防止惡意用戶的攻擊,凡是請求參數(shù)中表達(dá)式中含有等號(hào)(=),逗號(hào)(,),#號(hào)(#)的都是非法表達(dá)式,現(xiàn)在就去看一下具體是如何判斷一個(gè)參數(shù)是否合法的。

上面注釋也講到了,如果Action實(shí)現(xiàn)了ParameterNameAware,即要判斷ParameterNameAware接口中聲明的acceptableParameterName(name)方法(邏輯由自己實(shí)現(xiàn))也要判斷該攔截器的acceptableName(name)方法,我們這里假設(shè)Action沒有實(shí)現(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ù)過濾,配置了一個(gè)名為excludeParams的參數(shù),用于指定哪些參數(shù)要排除,即不合法,我們傳遞的時(shí)候是字符串在設(shè)置該字符串的時(shí)候該攔截器會(huì)對(duì)該字符串進(jìn)行解析轉(zhuǎn)化成相應(yīng)的Pattern對(duì)象以用于正則表達(dá)式校驗(yàn),而isAccepted與isExcluded方法中就是在用這些正則表達(dá)式進(jìn)行檢驗(yàn),邏輯很簡單,就說這么多。

最終進(jìn)行參數(shù)賦值是調(diào)用的ValueStack的setValue方法,該方法內(nèi)部使用是OGNL表達(dá)式引擎進(jìn)行賦值的,雖然內(nèi)部非常復(fù)雜,但我們只需要知道OGNL表達(dá)式引擎在把請求參數(shù)設(shè)置到ValueStack中時(shí),是從棧頂往棧底尋找有相應(yīng)setter方法的對(duì)象,如果正在賦值的參數(shù)在ValueStack找到了一個(gè)對(duì)象有setter方法則把該參數(shù)的值賦給該對(duì)象,如果沒有找到則繼承往棧底尋找,直到找到為止,如果找到棧底還是沒有找到也就沒有賦值成功。

到此該攔截器就講解完畢了,最后調(diào)用invocation.invoke();調(diào)用下一個(gè)攔截器......

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Springmvc自定義參數(shù)轉(zhuǎn)換實(shí)現(xiàn)代碼解析

    Springmvc自定義參數(shù)轉(zhuǎn)換實(shí)現(xiàn)代碼解析

    這篇文章主要介紹了Springmvc自定義參數(shù)轉(zhuǎn)換實(shí)現(xiàn)代碼解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • springmvc如何進(jìn)行異常處理

    springmvc如何進(jìn)行異常處理

    這篇文章主要介紹了springmvc如何進(jìn)行異常處理,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • SpringBoot 整合 Shiro 密碼登錄的實(shí)現(xiàn)代碼

    SpringBoot 整合 Shiro 密碼登錄的實(shí)現(xiàn)代碼

    這篇文章主要介紹了SpringBoot 整合 Shiro 密碼登錄的實(shí)現(xiàn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • Java之IO流面試題案例講解

    Java之IO流面試題案例講解

    這篇文章主要介紹了Java之IO流案例講解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • Spring Boot中使用Redis和Lua腳本實(shí)現(xiàn)延時(shí)隊(duì)列的方案

    Spring Boot中使用Redis和Lua腳本實(shí)現(xiàn)延時(shí)隊(duì)列的方案

    通過使用Redis和Lua腳本,可以在Spring Boot環(huán)境中實(shí)現(xiàn)一個(gè)高效且可靠的延時(shí)隊(duì)列系統(tǒng),這種方法利用了Redis的有序集合數(shù)據(jù)結(jié)構(gòu)和Lua腳本的原子性操作來確保任務(wù)的正確性和一致性,這篇文章主要介紹了Spring Boot中使用Redis和Lua腳本實(shí)現(xiàn)延時(shí)隊(duì)列,需要的朋友可以參考下
    2024-05-05
  • SpringCloud之Feign示例詳解

    SpringCloud之Feign示例詳解

    本篇文章主要介紹了SpringCloud之Feign示例詳解,詳細(xì)的介紹了Feign簡介和使用,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-01-01
  • Spring基于Aop實(shí)現(xiàn)事務(wù)管理流程詳細(xì)講解

    Spring基于Aop實(shí)現(xiàn)事務(wù)管理流程詳細(xì)講解

    這篇文章主要介紹了Spring基于Aop實(shí)現(xiàn)事務(wù)管理流程,事務(wù)管理對(duì)于企業(yè)應(yīng)用來說是至關(guān)重要的,即使出現(xiàn)異常情況,它也可以保證數(shù)據(jù)的一致性,感興趣想要詳細(xì)了解可以參考下文
    2023-05-05
  • Spring Boot項(xiàng)目使用Flyway的詳細(xì)教程

    Spring Boot項(xiàng)目使用Flyway的詳細(xì)教程

    這篇文章主要介紹了Spring Boot項(xiàng)目使用Flyway,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Spring Boot使用Druid和監(jiān)控配置方法

    Spring Boot使用Druid和監(jiān)控配置方法

    Druid是Java語言中最好的數(shù)據(jù)庫連接池,并且能夠提供強(qiáng)大的監(jiān)控和擴(kuò)展功能。下面來說明如何在 Spring Boot 中配置使用Druid
    2017-04-04
  • Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(6)

    Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(6)

    下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,希望可以幫到你
    2021-07-07

最新評(píng)論