<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    seaairland

     

    ActionServlet深入探討

    java.lang.Object
    ??|
    ??+--javax.servlet.GenericServlet
    ????????|
    ????????+--javax.servlet.http.HttpServlet
    ??????????????|
    ??????????????+--org.apache.struts.action.ActionServlet

    Struts提供了一個缺省版本的ActionServlet類,你可以繼承這個類,覆蓋其中的一些方法來達到你的特殊處理的需要。ActionServlet繼承與javax.servlet.http.HttpServlet,所以在本質(zhì)上它和一個普通的servlet沒有區(qū)別,你完全可以把它當做一個servlet來看待,只是在其中完成的功能不同罷了。ActionServlet主要完成如下功能:

    將一個來自客戶端的URI映射到一個相應的Action類
    • 如果是這個Action類是第一次被調(diào)用,那么實例化一個并放入緩存
    • 如果在配置文件(struts-config.xml)中指定了相應的ActionForm,那么從Request中抓取數(shù)據(jù)填充FormBean
    • 調(diào)用這個Action類的perform()方法,傳入ActionMapping的一個引用,對應的ActionForm、以及由容器傳給ActionServlet的HttpServletRequest、HttpServletResponse對象。


    確省版本的ActionServlet會從配置文件web.xml中讀取如下初始化參數(shù):
    • application
      應用使用的資源包(resources?bundle)的基類
    • factory
      用于創(chuàng)建應用的MessageResources對象的MessageResourcesFactory的類名。確省是org.apache.struts.util.PropertyMessageResourcesFactory。
    • config
      Struts的配置文件,確省是/WEB-INF/struts-config.xml。注意這兒是與應用Context關聯(lián)的相對路徑。
    • content
      定義了確省的內(nèi)容類型和編碼格式,它會被自動地被設置到每個response中,如果JSP/Servlet中沒有明確的設置。確省是text/html。
    • debug
      調(diào)試信息的級別。默認為0,比當前級別高的調(diào)試信息會被log到日志文件中。
    • detail
      與debug的作用類似,只是這個detail是initMapping()時專用的。調(diào)試信息會被打印到System.out,而不是日志文件。
    • formBean
      ActionFormBean的實現(xiàn)類,確省為org.apache.struts.action.ActionFormBean
    • forward
      應用中使用的ActionForward類,確省是org.apache.struts.action.ActionForward。
    • locale
      指定了確省使用的Locale對象。設為true,當?shù)玫揭粋€session時,會自動在session中存儲一個以Action.LOCALE_KEY標示的Locale對象,如果session中還沒有與Action.LOCALE_KEY綁定的Locale對象。
    • mapping
      應用中使用的ActionMapping類,確省是org.apache.struts.action.ActionMapping。
    • multipartClass
      文件上傳使用的MutipartRequestHandler的實現(xiàn)類。確省為org.apache.struts.upload.DiskMultipartRequestHandler
    • nocache
      如果設為true,那么ActionServlet會自動在每個到客戶端的響應中添加nocache的HTML頭,這樣客戶端就不會對應用中的頁面進行緩存。確省為false
    • null
      如果設置為true,那么應用在得到一個未定義的message資源時,會返回null,而不是返回一個錯誤信息。確省是true。
    • maxFileSize
      文件上傳的大小上限,確省為250M
    • bufferSize
      文件上傳時的緩沖區(qū)的大小,確省為4M
    • tempDir
      設置用于上傳時的臨時目錄。工作目錄會作為一個Servlet環(huán)境(Context)的屬性提供。
    • validate
      Are?we?using?the?new?configuration?file?format?確省為true。
    • validating

    在解析配置XML文件是是否進行有效性的驗證。確省為true

    ActionServlet中應用了命令設計模式。

    一個Servlet在由容器生成時,首先會調(diào)用init()方法進行初始化,在接到一個HTTP請求時,調(diào)用相應的方法進行處理;比如GET請求調(diào)用doGet()方法,POST請求調(diào)用doPost()方法。所以首先看看ActionServlet的init()方法,你就會很清楚為什么ActionServlet可以完成這些功能了。

    init()


    在它的init()方法中,ActionServlet依次調(diào)用如下protected的方法完成初始化:
    • initActions()?-?????大家可能還曾有這個疑問:Struts為什么可以找到一個請求URI對應的action類呢?答案就在這兒,ActionServlet有一個actions屬性,類型為org.apache.struts.util.FastHashMap,用于存儲以類的全名為key的已實例化的Action類。在init()時首先調(diào)用的就是initActions()方法,在這個方法中只是簡單的清除map中的所有的名值對,

      ????????synchronized?(actions)?{
      ????????????actions.setFast(false);
      ????????????actions.clear();
      ????????????actions.setFast(true);
      ????????}

      首先把actions設為slow模式,這時對FastHashMap的訪問是線程同步的,然后清除actions中的所有的已存在的名/值對,最后再把actions的模式設為fast。由于FastHashMap是struts在java.util.HashMap的基礎上的一個擴展類,是為了適應多線程、并且對HashMap的訪問大部分是只讀的特殊環(huán)境的需要。大家知道java.util.HashMap是非線程安全的,所以HashMap一般適用于單線程環(huán)境下。org.apache.struts.FastHashMap就是繼承于java.util.HashMap,在其中添加多線程的支持產(chǎn)生的。在fast模式下的工作方式是這樣的:讀取是非線程同步的;寫入時首先克隆當前map,然后在這個克隆上做寫入操做,完成后用這個修改后的克隆版本替換原來的map。那么在什么時候會把Actions類添加到這個map中呢?我們已經(jīng)提到了struts是動態(tài)的生成Action類的實例的,在每次ActionServlet接收到一個GET或POST的HTTP請求時,會在這個map中查找對應的Action類的實例,如果不存在,那么就實例化一個,并放入map中。可見這個actions屬性起到了對Action類實例的緩存的作用。
    • initInternal()?-?????初始化ActionServlet內(nèi)部使用的資源包MessageResources,使用MessageResources.getMessageResources(internalName)得到????internalName為"org.apache.struts.action.ActionResources"對應的ActionResources.properties文件。這個資源包主要用于ActionServlet處理過程中的用到的提示信息,這兒不展開討論。
    • initDebug()?-?????從web.xml中讀取本應用的debug級別參數(shù)getServletConfig().getInitParameter("debug"),然后賦給debug屬性。
    • initApplication()-????初始化應用資源包,并放置入ServletContext中。

      ????????String?factory?=getServletConfig().getInitParameter(“factory”);????
      ????????String?oldFacory?=?MessageResourcesFactory.getFactoryClass();
      ????????if?(factory?!=null)
      ????????????????MessageResourcesFactory.setFactoryClass(factory);
      ????????String?value?=?getServletConfig().getInitParameter("application");
      ????????MessageResourcesFactory?factoryObject?=
      ????????????????MessageResourcesFactory.createFactory();
      ????????application?=?factoryObject.createResources(value);
      ????????MessageResourcesFactory.setFactory(oldFactory);?
      ????????getServletContext().setAttribute(Action.MESSAGES_KEY,?application);

      說明:文中引用的代碼片斷可能會省略了一些例外檢查等非主線的內(nèi)容,敬請注意。

      首先從配置文件中讀取factory參數(shù),如果這個參數(shù)不為空,那么就在MessageResourcesFactory中使用這個指定的Factory類;否則,使用默認的工廠類org.apche.struts.util.PropertyMessageResourceFactory。然后調(diào)用MessageResourcesFactory的靜態(tài)createFactory()方法,生成一個具體的MessageResourceFactory對象(注意:MessageResourcesFactory是抽象類)。這樣就可以調(diào)用這個具體的MessageResourceFactory的createResource()方法得到配置文件(web.xml)中定義的資源文件了。
      上面的application對象類型為MessageResources。在web.xml中在配置ActionServlet時可以指定一個特定的工廠類。不能直接MessageResourcesFactory的createResources()方法,因為這個方法是abstract的。創(chuàng)建factoryObject的過程如下:
      ????
      ????????MessageResourceFactory?factoryObject=
      ????????????????MessageResourcesFactory.createFactory();
      ????????application?=?factoryObject.createResources(value);

      <li>initMapping()?-????為應用初始化mapping信息ActionServlet有一個protected的屬性:mapping,封裝了一個ActionMapping的對象集合,以便于管理、查找ActionMapping。mappings是org.apache.struts.action.ActionMappings類的實例。主要有兩個方法:addMapping(ActionMapping?mapping)和findMapping(String?path)。ActionMapping也是使用上面提到的org.apache.struts.util.FastHashMap類來存儲所有的ActionMapping對象。

      ????????mappings.setServlet(this);
      ????????……
      ????????//?Initialize?the?name?of?our?ActionFormBean?implementation?class
      ????????value?=?getServletConfig().getInitParameter("formBean");
      ????????if?(value?!=?null)
      ????????????formBeanClass?=?value;
      ????
      ????????//?Initialize?the?name?of?our?ActionForward?implementation?class
      ????????value?=?getServletConfig().getInitParameter("forward");
      ????????if?(value?!=?null)
      ????????????????forwardClass?=?value;

      ????????//?Initialize?the?name?of?our?ActionMapping?implementation?class
      ????????value?=?getServletConfig().getInitParameter("mapping");
      ????????if?(value?!=?null)
      ????????????????mappingClass?=?value;

      在initMapping()中,首先鏈接mappings對象到本servlet實例。其實這句話的作用很簡單,在ActionMappings中會有一個ActionServlet類型的屬性,這個屬性就界定了這個ActionMappings對象所屬的ActionServlet。Struts的實現(xiàn)比較靈活,其中的ActionFormBean、ActionForward、ActionMapping類你完全可以使用自己實現(xiàn)的子類,來定制Struts的工作方式。上面的代碼就從配置文件(web.xml)中讀取formBean、forward、mapping參數(shù),這些參數(shù)就是你定制的ActionFormBean、ActionForward、ActionMapping類名。

      ????????//?Initialize?the?context-relative?path?to?our?configuration?resources
      ????????value?=?getServletConfig().getInitParameter("config");
      ????????if?(value?!=?null)
      ????????????????config?=?value;
      ????????????????//?Acquire?an?input?stream?to?our?configuration?resource
      ????????InputStream?input?=?getServletContext().getResourceAsStream(config);
      ????????Digester?digester?=?null;
      ????????????????digester?=?initDigester(detail);
      ????????try?{
      ????????????????formBeans.setFast(false);
      ????????????????forwards.setFast(false);
      ????????????????mappings.setFast(false);
      ????????????????digester.parse(input);
      ????????????????mappings.setFast(true);
      ????????????????forwards.setFast(true);
      ????????????????formBeans.setFast(true);
      ????????}?catch?(SAXException?e)?{
      ????????????????throw?new?ServletException
      ????????(internal.getMessage("configParse",?config),?e);
      ????????}?finally?{
      ????????????????input.close();
      ????????}

      從web.xml讀取Struts的配置文件的位置。使用org.apache.struts.digester.Digester解析config參數(shù)標示的配置文件,通常為“/WEB-INF/struts-config.xml”,解析出所有的data-source、form-bean、action-mapping、forward。從上面的程序片斷看到,Digester僅僅調(diào)用了一個parse()方法,那么,Digester是怎樣把解析struts-config.xml文件并把解析的結(jié)果form-bean等信息存儲到屬性變量formBeans等中的呢?你可以注意到在調(diào)用digester.parse(InputStream)之前,首先調(diào)用了initDigester()方法:

      ????????Digester?digester?=?new?Digester();
      ????????digester.push(this);
      ????????digester.addObjectCreate("struts-config/action-mappings/action",
      ?????????????????????????????????mappingClass,?"className");
      ????????digester.addSetProperties("struts-config/action-mappings/action");
      ????????digester.addSetNext("struts-config/action-mappings/action",
      ????????????????????????????"addMapping",
      ????????????????????????????"org.apache.struts.action.ActionMapping");

      ????????digester.addSetProperty
      ????????????("struts-config/action-mappings/action/set-property",
      ?????????????"property",?"value");

      在這個方法中首先生成一個Digester對象,然后設置解析的規(guī)則和回調(diào),如果你對XML、SAX不是很熟,這兒不必糾纏太深。要注意的是addSetNext()方法,設置了每一個要解析元素的Set?Next回調(diào)方法,而這個方法就是由digester解析器的父提供的。上面的片斷中的“addMapping”就是ActionServlet本身定義的一個方法,將由Digester回調(diào)。Digester就是籍此把解析出的每一個FormBean、ActionForward、ActionMapping等存儲到屬性變量formBeans、forwards、mappings等中的。
    • initUpload()?-????初始化有關Upload的一些參數(shù),比如:bufferSize、tempDir。
    • initDataSource()?-取出在initMapping()中從配置文件中讀取的每一個DataSource,設置LogWriter,如果為GenericDataSource的實例,則打開數(shù)據(jù)源。然后,把每個dataSource放入Context中。
      dataSource.setLogWriter(scw);
      ((GenericDataSource)dataSource).open();
      getServletContext().setAttribute(key,dataSource);
    • initOther()?-????????設置其它尚未初始化的的參數(shù)(content、locale、nocache),并發(fā)布formBeans、forwards、mappings到Context:
      getServletContext().setAttribute(Action.FORM_BEANS_KEY,?formBeans);
      getServletContext().setAttribute(Action.FORWARDS_KEY,?forwards);
      getServletContext().setAttribute(Action.MAPPINGS_KEY,?mappings);
    • initServlet()?-????初始化Controller?Servlet的Servlet?Mapping。這兒也使用了Digester工具,掃描web.xml所有的<web-app/servlet-mapping>,尋找servlet-name與當前Servlet相同的mapping,置入Context。代碼如下;

      ????????Digester?digester?=?new?Digester();
      ????????digester.push(this);
      ????????digester.setDebug(debug);
      ????????digester.setValidating(validating);
      ????????digester.addCallMethod(“web-app/servlet-mapping”,“addServletMapping”,?2);
      ????????digester.addCallParm(“web-app/servlet-mapping/servlet-name”,?0);
      ????????digester.addCallParm(“web-app/servlet-mapping/url-pattern”,?1);
      ????????InputStream?is?=?getServletContext().getResourceAsStream(“/WEB-INF/web.xml”);
      ????????digester.parse(is);?
      ????????getServletContext().setAttribute(Action.SERVLET_KEY,servletMapping);

    posted on 2006-05-25 14:23 chenhui 閱讀(447) 評論(0)  編輯  收藏


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導航:
    博客園   IT新聞   Chat2DB   C++博客   博問  
     

    導航

    統(tǒng)計

    常用鏈接

    留言簿(1)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    介紹 IOC

    友情鏈接

    最新隨筆

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: free哆啪啪免费永久| 久久这里只精品国产免费10| 日本精品久久久久久久久免费| 黄色免费网址大全| 中国国语毛片免费观看视频| 精品无码人妻一区二区免费蜜桃| 免费精品国产日韩热久久| 日本媚薬痉挛在线观看免费| 精品国产亚洲男女在线线电影| 亚洲国产成人久久精品动漫 | 国内精自视频品线六区免费| 在线播放免费人成视频在线观看| 免费又黄又硬又爽大片| 亚洲精品中文字幕无码蜜桃| 亚洲国产综合精品| 老司机午夜性生免费福利 | 日日躁狠狠躁狠狠爱免费视频| 色www永久免费| 亚洲第一成年免费网站| 免费h成人黄漫画嘿咻破解版| 亚洲av无码乱码国产精品fc2| 亚洲欧美日韩国产精品一区| 久久www免费人成看国产片| 国产福利视精品永久免费| 免费在线观看a级毛片| 久久精品国产精品亚洲色婷婷| 亚洲老熟女五十路老熟女bbw| 热久久这里是精品6免费观看| 国产免费看JIZZ视频| 国产精品xxxx国产喷水亚洲国产精品无码久久一区 | 亚洲国产精品精华液| 在线观看特色大片免费网站 | 免费一级不卡毛片| 免费毛片在线播放| 亚洲av日韩av高潮潮喷无码| 亚洲精品无码少妇30P| 玖玖在线免费视频| 国产公开免费人成视频| 亚洲色偷偷偷网站色偷一区| 又粗又长又爽又长黄免费视频 | 国产亚洲精久久久久久无码AV|