国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
struts源代碼閱讀(struts 的執(zhí)行)
第二篇  struts的執(zhí)行(struts-1.1版)

本篇詳細介紹struts在初始化之后是如何處理一個請求,并返回數(shù)據(jù)的。這里最核心的類是
requestprocessor以及requestutils。requestprocessor類通過requestdispatcher實現(xiàn)頁面的跳轉(zhuǎn),
而requestprocessor負(fù)責(zé)處理request中傳來的請求信息,存放到formbeanconfig中,以及對要跳轉(zhuǎn)的
url進行處理。

struts 在初始化完成之后,會根據(jù)請求調(diào)用doget(...)或者dopost(...)方法,這兩個方法直接
調(diào)用process(request, response)方法。process(...)方法首先判斷當(dāng)前的request屬于
哪一個moduleconfig,然后生成與這個moduleconifg相對應(yīng)的requestprocessor,最后調(diào)用這個
requestprocessor的process(...)方法,執(zhí)行request的請求。

一、requestutils.selectmodule(string prefix, httpservletrequest,servletcontext)方法:
    這個方法,根據(jù)prefix,從servletcontext中選擇相應(yīng)的moduleconfig,然后把這個moduleconfig
    保存到request中。servletcontext對應(yīng)的key值為globals.module_key + prefix,保存到request
    中使用的key值為globals.module_key。如果在servletcontext中不存在這樣的一個moduleconfig,
    那么調(diào)用request.removeattribute(globals.module_key)方法。然后以同樣的方法查找、保存
    messageresources對象。當(dāng)prefix為空時,會調(diào)用下面的方法選擇moduleconfig。

二、requestutils.selectmodule(httpservletrequest, servletcontext)
    這個方發(fā)首先使用getmodulename(httpservletrequest, servletcontext)獲取相應(yīng)的path,然后
    通過調(diào)用getmodulename(string matchpath, servletcontext)獲取相應(yīng)的prefix。以這prefix為
    參數(shù)調(diào)用(一)中的selectmodule(...)選擇moduleconfig。
    獲取path的過程為:首先從request中查找名稱為
    include_servlet_path(javax.servlet.include.servlet_path)的屬性,如果為空,就調(diào)用
    request.getservletpath()方法獲取servletpath。

    獲取prefix的過程為:它首先調(diào)用getmoduleprefixes(servletcontext),獲取所有已存在的
    module前綴。 然后通過分析上面獲取的path來判斷當(dāng)前的url屬于哪一個module,方法是截取
    path中最后一個"/"字符前面的字符串,然后與有上面方法中獲取的prefixes[]逐個對比,如果
    prefixes[]中存在這樣的一個值,則返回這個截取的字符串,否則繼續(xù)截取path最后面的"/"前面
    的字符串,然后對比。如果始終找不到,則返回""。

    getmoduleprefixes(servletcontext)的執(zhí)行過程是:首先通過
    context.getattribute(prefixes_key)查找是否存在這樣的一個保存所有的prefix的string array,
    如果存在,就說明已經(jīng)解析過一次了,就直接返回這個string array,否則遍歷servletcontext中
    所有的attribute name,查找以module_key(org.apache.struts.action.module)開頭的
    atrribute name,然后截取這個atrribute name中module_key后面的字符串,作為一個prefix. 最
    后把通過這個這個方式獲取的所有的prefix作為一個arraylist存儲到servletcontext中,屬性key
    值為prefixes_key(org.apache.struts.util.prefixes),這樣下次再次查找的時候就可以直接從這
    個attribute中獲取了。

三、getmoduleconfig(httpservletrequest)
    這個方法就是獲取上面的selectmodule(...)方法所得到的moduleconfig。如果找不到這樣的
    moduleconfig,那么就把servletcontext中缺省的moduleconfig返回(調(diào)用
    getservletcontext().getattribute(globals.module_key))

四、getrequestprocessor(moduleconfig config)
    這個方法從根據(jù)moduleconfig的prefix作為key,從servletcontext中獲取requestprocessor。這
    個key值為globals.request_processor_key + config.getprefix()。

    如果servletcontext中不存在這樣的一個requestprocessor,那么就生成一個新的
    requestprocessor的實例,完成初始化(保存actionservlet以及moduleconfig到這個新的實例中)后
    將其保存到servletcontext中。

五、requestprocessor.process(httpservletrequest, httpservletresponse)
    這是真正執(zhí)行httpservletrequst請求的方法。

    這個方法首先判斷但前的httpservletrequest是否是multipart類型的request,也就是說當(dāng)前
    的request是否有字段是"file"類型。這樣做的原因是這種類型的request中g(shù)etparameter()等
    相類似的方法都是無法執(zhí)行的,所以要區(qū)分對待。如果是multipart類型的,那么把這個request包
    裝成multipartrequestwrapper類。

    multipartrequestwrapper 與 httpservletrequest不同的就是重新實現(xiàn)了
    setparameter(string name, string value),getparameter(string name),getparameternames()
    以及getparametervalues(string name)方法。
    這些方法的思想是所有的變量名、值對都保存到一個hashmap里:key為變量名,value為變量值,但
    是注意value都是string[]格式的。當(dāng)有一個新的值加入的時候,通過setparameter(...)
    方法,把值加到數(shù)組的最后。在setparameter(...)中有一個比較少見的保存值的方法,記錄如下:
    public void setparameter(string name, string value) {
        string[] mvalue = (string[]) parameters.get(name);
        if (mvalue == null) {
            mvalue = new string[0];
        }
        string[] newvalue = new string[mvalue.length + 1];
        system.arraycopy(mvalue, 0, newvalue, 0, mvalue.length);
        newvalue[mvalue.length] = value;
        
        parameters.put(name, newvalue);
    }

    然后是調(diào)用processpath(httpservletrequest, httpservletresponse)獲取地址,以這個地址作為
    從moduleconfig獲取actionmapping的key。這里首先查詢
    request.getattribute(include_path_info)中是否有這樣的一個值,如果為空就調(diào)用
    request.getpathinfo()方法獲取path。如果這樣還是獲取不了,就從
    request.getattribute(include_servlet_path)方法中獲取path,找不到就使用
    request.getservletpath()得到的path進行分析。分析過程如下:

    然后如果這個path不是屬于當(dāng)前的moduleconfig的話,直接返回null。截取prefix后面的字符串,
    如果這個字符串以.xx結(jié)尾,那么就截取"."前面的字符,比如
    http://localhost:8080/servlet/where/go.do。where為module的名稱(prefix),那么我們獲取的
    path值為/go。

    然后是通過processlocale(httpservletrequest ,httpservletresponse)為當(dāng)前用戶設(shè)定一個local
    對象,它查找的順序是:moduleconfig.getcontrollerconfig().getlocale(),
    session.getattribute(globals.locale_key),request.getlocale()。你可以在config xml文件
    中通過<controller><set-property..../></controller>執(zhí)行相關(guān)的定義。

    調(diào)用processcontent(httpservletrequest, httpservletresponse)為response設(shè)定contenttype。
    這個contenttype是從moduleconfig.getcontrollerconfig().getcontenttype()獲取的。你可以
    在config xml文件中通過<controller><set-property..../></controller>執(zhí)行相關(guān)的定義。

    通過processnocache(httpservletrequest, httpservletresponse)方法設(shè)置response的緩存。
    你可以在config xml文件中通過<controller><set-property..../></controller>執(zhí)行相關(guān)的定義。

    processpreprocess(httpservletrequest, httpservletresponse)預(yù)處理request,這個方法是預(yù)
    留的,用戶可以根據(jù)自己的需要加一些預(yù)處理的程序。

    通過processmapping(httpservletrequest, httpservletresponse, string path)以
    processpath(...)的返回值為key從moduleconfig中查找actionmapping 對象。如果找到了,那么保
    存這個mapping到request中,key值為globals.mapping_key。如果不存在,那么遍歷moduleconfig
    中所有的actionmapping,查找哪一個是缺省的actionmapping。然后把它保存到request中,key值
    為globals.mapping_key。

    通過processroles(httpservletrequest,httpservletresponse,actionmapping)檢查當(dāng)前用戶是
    否有權(quán)限執(zhí)行這個請求。如果request.isuserinrole(roles[i])返回true,則代表有。

    通過processactionform(httpservletrequest, httpservletresponse, actionmapping)生成一個
    actionform,然后根據(jù)actionmapping所屬的scope,保存到request或者session中。key值為這個
    actionmapping中的attribute屬性。actionform是通過requestutils.createactionform(...)方法
    獲取的,在下一篇將會對這個方法進行詳細的說明。這里只說明actionform與formbeanconfig以及
    formpropertyconfig之間的區(qū)別。每個formpropertyconfig代表form表單的一個字段,表單中的所
    有formpropertyconfig以一個hashmap保存到formbeanconfig中。而formbeanconfig是在
    actionservet初始化的時候生成的:
    <form-beans>
      <form-bean name="一個名稱,作為action選擇的key" type="實際對應(yīng)的actionform類"/>
    <form-beans>
    名稱用來在moudleconfig中的formbeans hashmap中查找相應(yīng)的formbeanconfig,而formbeanconfig
    中有一個type,它保存了上面xml文件中定義的值,用來生成actionform。
    
    通過processpopulate(httpservletrequest, httpservletresponse, actionform,
    actionmapping)方法初始化actionform 以及 formbean,這個方法首先會設(shè)定這個actionform所屬
    于的actionservlet,然后對這個actionform進行初始化。判斷當(dāng)前的reqest是否multipart類型,
    如果是就把相應(yīng)的multipartclass類全名保存到request中,key值為globals.multipart_key。調(diào)
    用requestutils.populate(...)對request中的參數(shù)進行處理,并保存到相應(yīng)的formbean中。在下
    一篇將會對這個方法進行詳細的說明。最后根據(jù)request的parameter判斷當(dāng)前的請求是否是被取
    消,然后把相關(guān)信息保存到request中:
    if ((request.getparameter(constants.cancel_property) != null)
         (request.getparameter(constants.cancel_property_x) != null)) {
        request.setattribute(globals.cancel_key, boolean.true);
    }

六、下面說明這個request是如何真正被處理的,下面的方法都是在requestprocessor中定義。

    通過processvalidate(httpservletrequest, httpservletresponse, actionform,
    actionmapping)判斷request中的parameter是否合法。如果合法就返回true,否則取消這次請求,
    并且返回到指定的輸入頁面。它判斷合法的過程是:如果這次的請求被取消,那么直接返回true;
    如果沒有要求對request中的parameter進行合法性檢驗,也直接返回true;最后通過調(diào)用
    form.validate(mapping, request)執(zhí)行檢驗,如果返回的actionerrors為null,那么代表通過
    檢驗,返回true,否則取消這次request。取消的過程是:如果這個請求是multipart類型的,那么
    要對這個multipartrequesthandler進行回滾;而后,獲取當(dāng)前的actionmapping的input值,即在
    config xml 中<action.../>定義的input屬性。如果actionmapping沒有這個input值,那么調(diào)用
    response.senderror(...)方法,然后返回false;如果存在,就保存驗證出錯信息到request中,
    key為globals.error_key,跳轉(zhuǎn)到input所指定的地址中。

    processforward(httpservletrequest, httpservletresponse, actionmapping)以及
    processinclude(httpservletrequest, httpservletresponse, actionmapping)分別通過執(zhí)行
    requestdispatcher.forward(request, response) 以及 requestdispatcher.include(request,
    response)實現(xiàn)對頁面的跳轉(zhuǎn)。
    
    但是如果當(dāng)前的請求還有其它操作要執(zhí)行,那么actionmapping中的include或者forward屬性值就
    會為空。這時需要通過調(diào)用processactioncreate(httpservletrequest, httpservletresponse,
    actionmapping)方法根據(jù)config xml文件的配置信息生成一個action類,然后通過
    processactionperform(...)調(diào)用生成的action中的execute(...)方法。最后根據(jù)execute(...)
    方法返回的actionforword類,執(zhí)行跳轉(zhuǎn)。在整個過程中有一個url的計算方法,這個將在下一篇
    中說明。


七、對actionmaping結(jié)構(gòu)的說明:
    在actionconfig為保存moudle action屬性的一個javabean,它有以下屬性:
    * boolean configured 這個對象的所有屬性是否已經(jīng)被配置完。如果已經(jīng)完成,那么在改變其中
      任何屬性都會拋出illegalstateexception("configuration is frozen")
    * moduleconfig moduleconfig 本actionconfig類所屬于的moduleconfig。
    * string attribute request范圍 或者 session范圍 的屬性名稱,我們將通過這個屬性名稱來
      獲取相應(yīng)的form bean,注意,這個屬性與form bean中定義的名稱是不一樣的。注意以下的方
      法:
      public string getattribute() {
          if (this.attribute == null) {
              return (this.name);
          } else {
              return (this.attribute);
          }
      }
    * string forward 調(diào)用requestdispatcher.forward()方法時所需要的上下文相關(guān)的地址。
    * string include 調(diào)用requestdispatcher.include()方法時所需要的上下文相關(guān)的地址。
    * string type action類的類全名,如果上面的兩個屬性都沒有定義的話,就會用它來處理
      request。
    * string input 如果輸入數(shù)據(jù)沒有通過驗證,將會以這個值為地址,跳轉(zhuǎn)到相應(yīng)的頁面。
    * string multipartclass multipartrequesthandler實現(xiàn)類的全名
    * string name 與本類相關(guān)的 form bean 的名稱。
    * string parameter 用于struts的擴展,存儲其它的配置信息。struts自己不會用到這個屬性。
    * string path 上下文相關(guān)的地址,這個地址為下一個將會進入的地址,這個地址必須要以"/"
      開頭。如果使用了extension mapping的話,這個地址將不會帶有擴展名。
    * string roles 一個以","分隔的角色名稱。這些角色將會有權(quán)限訪問這個request。
    * string scope 缺省為session。
    * string prefix,string suffix后綴和前綴。
    * boolean unknown 標(biāo)志當(dāng)前的actionconfig類是否是為了未知的request path而準(zhǔn)備的,
      actionmappings將會根據(jù)這個標(biāo)志返回這個actionconfig。
    * boolean validate 是否調(diào)用validate()方法進行數(shù)據(jù)校驗。    

    actionmapping 繼承自 actionconfig,它增加了從moduleconfig查找actionforword的方法。同
    時它還提供了從moduleconfig查找exceptionconfig的方法,如果找不到,會通過
    type.getsuperclass()方法,根據(jù)父類的類名稱繼續(xù)查找,直到最后。

八、關(guān)于request.getservletpath()的解釋:
    request.getservletpath() 的返回值就是在下面url中定義的值,比如如果按照下面的定義
    <url-pattern>
      *.do
    </url-pattern>
    那么:
    http://localhost:8080/servlet/go.do ---------->/go.do
    http://localhost:8080/servlet/where/go.do ---------->/where/go.do
    這里有一個小常識,如果
    <url-pattern>
      /where/*.do
    </url-pattern>
    那么地址中只有http://localhost:8080/servlet/where/*.do有效(tomcat 4.0)


    在actionconfig為保存moudle action屬性的一個javabean,它有以下屬性:
    * boolean configured 這個對象的所有屬性是否已經(jīng)被配置完。如果已經(jīng)完成,那么在改變其中
      任何屬性都會拋出illegalstateexception("configuration is frozen")
    * moduleconfig moduleconfig 本actionconfig類所屬于的moduleconfig。
    * string attribute request范圍 或者 session范圍 的屬性名稱,我們將通過這個屬性名稱來
      獲取相應(yīng)的form bean,注意,這個屬性與form bean中定義的名稱是不一樣的。注意以下的方
      法:
      public string getattribute() {
          if (this.attribute == null) {
              return (this.name);
          } else {
              return (this.attribute);
          }
      }
    * string forward 調(diào)用requestdispatcher.forward()方法時所需要的上下文相關(guān)的地址。
    * string include 調(diào)用requestdispatcher.include()方法時所需要的上下文相關(guān)的地址。
    * string type action類的類全名,如果上面的兩個屬性都沒有定義的話,就會用它來處理
      request。
    * string input
    * string multipartclass multipartrequesthandler實現(xiàn)類的全名
    * string name 與本類相關(guān)的 form bean 的名稱。
    * string parameter 用于struts的擴展,存儲其它的配置信息。struts自己不會用到這個屬性。
    * string path 上下文相關(guān)的地址,這個地址為下一個將會進入的地址,這個地址必須要以"/"
      開頭。如果使用了extension mapping的話,這個地址將不會帶有擴展名。
    * string roles 一個以","分隔的角色名稱。這些角色將會有權(quán)限訪問這個request。
    * string scope 缺省為session。
    * string prefix,string suffix后綴和前綴。
    * boolean unknown 標(biāo)志當(dāng)前的actionconfig類是否是為了未知的request path而準(zhǔn)備的,
      actionmappings將會根據(jù)這個標(biāo)志返回這個actionconfig。
    * boolean validate 是否調(diào)用validate()方法進行數(shù)據(jù)校驗。    

    actionmapping 繼承自 actionconfig,它增加了從moduleconfig查找actionforword的方法。同
    時它還提供了從moduleconfig查找exceptionconfig的方法,如果找不到,會通過
    type.getsuperclass()方法,根據(jù)父類的類名稱繼續(xù)查找,直到最后。
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
JR 精品文章 - 使用Timmer使Struts修改struts-config.xml文...
Go 語言內(nèi)置的 Handler
struts2 處理請求流程分析(結(jié)合源碼)2
struts源代碼閱讀(struts 初始化)
擴展struts
Struts第一天
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服