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

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

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

    爪哇東南的自留地

    學習探討開源和web開發(fā)

    導航

    <2006年9月>
    272829303112
    3456789
    10111213141516
    17181920212223
    24252627282930
    1234567

    統(tǒng)計

    常用鏈接

    留言簿(1)

    隨筆分類

    隨筆檔案

    相冊

    收藏夾

    life

    technique

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    Struts初始化

    我在幾個月前曾經發(fā)表過一個帖子,就是和大家一起學習struts源代碼。成為一名合格的程序員,閱讀大量的優(yōu)秀程序是必不可少的。只看書是不會讓你水平有很大提高的,要多看多寫。
    本來是打算等下面幾篇文章寫好后一起發(fā)布的,這樣大家可能才能看得明白些,但是根據(jù)我現(xiàn)在的狀況,估計還要一、兩個月。所以,為了防止在struts源代碼發(fā)生過大變化后我的文章就沒有太大價值了,所以就提前發(fā)表了,霍霍~~~
    我的email為:mariah_fan@hotmail.com,有什么不對的地方請大家指正:)
    struts作為J2EE的MVC框架已經取得了很大的成功,下面將分幾篇文章說明struts源程序的結構。
    第一篇? struts的初始化

    struts 的核心類是org.apache.struts.action.ActionServlet,這個類將會在struts第一次使用時,
    作為servlet初始化并存入tomcat容器。很顯然的,初始化將會調用init方法初始化相應的數(shù)據(jù)。

    一、initInternal()方法:
    ??? 通過調用MessageResources.getMessageResources(internalName)方法生成一個
    ??? MessageResources類,getMessageResources是通過調用MessageResourcesFactory.
    ??? createResources(config)來實現(xiàn)的。至于MessageResourcesFactory是一個abstract類,任何
    ??? 繼承自它的類都要實現(xiàn)createResources方法,生成MessageResources對象。整個程序生成
    ??? MessageResourcesFactory使用了如下技巧:
    ??? MessageResourcesFactory.factoryClass = factoryClass;
    ??? MessageResourcesFactory.clazz = null;
    ??? 首先會通過factoryClass來定義一個類全名,然后通過ClassLoader.loadClass
    ??? (factoryClass)方法來生成這個類,并賦給clazz,然后通過newInstance來生成一個對象。
    ??? 在本程序中,生成MessageResources對象實際就是對如下屬性進行了初始化:
    ??? this.factory = factory;("org.apache.struts.util.PropertyMessageResourcesFactory")
    ??? this.config = config;("org.apache.struts.action.ActionResources")
    ??? this.returnNull = returnNull;(true/false)

    ??? 對于MessageResources類的作用是根據(jù)不同的Locate來格式化相應的string。或者把你需要改變
    ??? 的string存放到數(shù)組中,然后通過getMessage(Locale locale, String key, Object args[])
    ??? 方法來格式化。然后把格式好的string存放到HashMap里,這樣就可以為以后重用。這里的key是
    ??? 使用的locale.toString() + "." + key

    ??? 在PropertyMessageResources中的loadLocale方法用來讀取resource的初始化信息。首先它會
    ??? 通過一個HashMap檢測這個localKey相關的message是否已經被初始化了,如果被初始化過就跳
    ??? 出,檢測的方法是locales.get(localeKey) != null。
    ??? 然后會讀取如下一個文件:
    ??? org/apache/struts/action/ActionResources_(localKey).properties,然后進行如下操作:
    ??? Properties props = new Properties();
    ??? ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    ??? is = classLoader.getResourceAsStream(name);
    ??? props.load(is);
    ??? Iterator names = props.keySet().iterator();
    ??????? while (names.hasNext()) {
    ??????????? String key = (String) names.next();
    ??????????? if (log.isTraceEnabled()) {
    ??????????????? log.trace("? Saving message key '" + messageKey(localeKey, key));
    ??????????? }
    ??????????? messages.put(messageKey(localeKey, key), props.getProperty(key));
    ??? }

    ??? PropertyMessageResources 就是通過上面的loadLocale方法查找與Locale locale, String key
    ??? 相對對應的Message.查找的次序如下locale.toString(),然后是
    ??? localeKey = localeKey.substring(0, underscore),然后是defaultLocale,然后是key。

    ??? 最后,resource類的結構如下:
    ??? PropertyMessageResources extends MessageResources
    ??? PropertyMessageResourcesFactory extends MessageResourcesFactory

    二、initOther()方法:
    ??? 從servlet中獲取config和debug兩個參數(shù),然后初始化ConvertUtils對象。由于
    ??? ConvertUtils.deregister()的初始化,所有的Converter都是有初始值的,所以這里Struts自己
    ??? 把這些初始值設置為null,即轉換出錯的時候返回null,而不是初始值。使用ConvertUtils類的
    ??? 原因是由于從form傳輸過來的都是String類型的值,所以我們要把它們轉換成相應的類型。

    ??? 提到幾個技巧:
    ??? *public boolean isIndexed() {
    ???????? if (type == null) {
    ???????????? return (false);
    ???????? //技巧一:判斷是否是一個Array類的方法
    ???????? } else if (type.isArray()) {
    ???????????? return (true);
    ???????? //技巧二:判斷type是否是List的一個父類或者父接口,或者與List為同一個類
    ???????? //要注意如果List是另一個primitive的TYPE類,那么type必須也是這個類才會
    ???????? //返回true,否則都是false。注意long.TYPE與Long.class是不同的
    ???????? } else if (List.class.isAssignableFrom(type)) {
    ???????????? return (true);
    ???????? } else {
    ??????????? return (false);
    ???????? }
    ???? }

    ??? *//componentType為Array類所存儲的元素的類別
    ???? Class componentType = indexedProperty.getClass().getComponentType();
    ???? //生成一個新的Array
    ???? Object newArray = Array.newInstance(componentType, (index + 1));
    ???? System.arraycopy(indexedProperty, 0, newArray, 0, length);
    ???? indexedProperty = newArray;
    ???? set(name, indexedProperty);
    ???? int newLength = Array.getLength(indexedProperty);
    ???? for (int i = length; i < newLength; i++) {
    ??????? Array.set(indexedProperty, i, createProperty(name+"["+i+"]", componentType));
    ???? }

    三、initServlet()方法:
    ??? 這個方法主要是通過digester類解析web.xml,對String servletMapping屬性進行初始化。對于
    ??? digester說明如下:這是一個基于DOM的SAX實現(xiàn)的類,它是事件觸發(fā)的,根據(jù)xml文件的結構,
    ??? 每次讀到一個節(jié)點元素就會觸發(fā)一個事件。

    ??? InputStream input = getServletContext().getResourceAsStream("/WEB-INF/web.xml");
    ??? 這是一個比較少見的方法。首先通過this.servletName = getServletConfig().
    ??? getServletName()獲取servlet的名稱,然后根據(jù)
    ??? if (servletName.equals(this.servletName)) {
    ??????? this.servletMapping = urlPattern;
    ??? }
    ??? 來判斷當前讀到的servlet名稱是否是我們運行的servlet的名稱,如果是,就把url-pattern作為
    ??? 我們的servletMapping。

    四、getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this)
    ??? 把自己存儲到servletContext中,屬性名為Globals.ACTION_SERVLET_KEY。

    五、ModuleConfig moduleConfig = initModuleConfig("", config)
    ??? 這個方法使用由initOther()方法獲取的config值為要解析的xml路徑,用來初始化ModuleConfig。
    ??? 它首先采用與生成MessageResourcesFactory同樣的方法產生一個MessageResourcesFactory對象:
    ??? MessageResourcesFactory為一個抽象類,每一個繼承它的類都要實現(xiàn)
    ??? createModuleConfig(String prefix)方法。本程序使用的缺省的MessageResourcesFactory類為
    ??? org.apache.struts.config.impl.DefaultModuleConfigFactory,它
    ??? 的createModuleConfig(String prefix)方法會生成一個ModuleConfigImpl類。

    ??? ModuleConfigImpl類相當于一個JavaBean,用來存放一個web模塊運行時所需要的配置信息。當
    ??? 然,一個web模塊可以擁有多個ModuleConfig,但是缺省的是prefix長度為0的ModuleConifg。它
    ??? 的每個屬性幾乎都是由HashMap組成的,它通過一個configured布爾值來描述當前的ModuleConfig
    ??? 是否已經被初始化完畢,在每存放一個屬性的時候都會監(jiān)測這個值。如果初始化完畢而還要改變
    ??? 里面的屬性值,則會報出IllegalStateException("Configuration is frozen")異常,現(xiàn)在對它
    ??? 的屬性簡單說明如下:
    ??? * protected HashMap actionConfigs:
    ????? 這個HashMap用來存儲ActionConfig對象。
    ??? * protected HashMap dataSources
    ????? 這個HashMap用來存儲DataSourceConfig對象。
    ??? * protected HashMap exceptions
    ????? 這個HashMap用來存儲ExceptionConfig對象。
    ??? * protected HashMap formBeans
    ????? 這個HashMap用來存儲FormBeanConfig對象。
    ??? * protected HashMap forwards
    ????? 這個HashMap用來存儲ForwardConfig對象。
    ??? * protected HashMap messageResources
    ????? 這個HashMap用來存儲MessageResourcesConfig對象。
    ??? * protected ArrayList plugIns
    ????? 這個HashMap用來存儲PlugInConfig對象。
    ??? * protected ControllerConfig controllerConfig
    ????? ControllerConfig類
    ??? * protected boolean configured
    ????? 標志這個ModuleConfig是(true)否(false)配置完成。
    ??? * protected String prefix
    ????? 用來標志和區(qū)分ModuleConfig類,同時在使用上面的config類初始化相應的資源以后,也是通
    ????? 過這個prefix來區(qū)分所屬的不同的web模塊。
    ??? * protected String actionMappingClass = "org.apache.struts.action.ActionMapping"
    ????? ActionMapping類名,缺省為org.apache.struts.action.ActionMapping。

    ??? 初始化ModuleConfig的方法如下:
    ??? 首先是使用getServletConfig().getInitParameter("mapping")來獲取設定的ActionMapping類
    ??? 名,然后通過initConfigDigester()方法來生成一個digester。最后用","分隔config,對每一
    ??? 塊調用parseModuleConfigFile(prefix, paths, config, digester, path)方法解析。注意,這
    ??? 個方法實際上只有兩個參數(shù)是有意義的:path為我們要解析的xml文件,config用來初始化完成
    ??? 后保存到servletContext中。

    ??? 如果ModuleConfig中存放的FormBeanConfig為Dydamic類型,那么就調用
    ??? DynaActionFormClass.createDynaActionFormClass(FormBeanConfig)初始化
    ??? DynaActionFormClass,并存放到DynaActionFormClass.dynaClasses 的 static HashMap中。這
    ??? 里的key為FormBeanConfig.getName() + moduleConfig.getPrefix()。
    ???
    ??? 如果當前的ModuleConfig為缺省的ModuleConfig,那么將會調用如下幾個方法:
    ??? defaultControllerConfig(config)
    ??? defaultMessageResourcesConfig(config)
    ??? defaultFormBeansConfig(config)
    ??? defaultForwardsConfig(config)
    ??? defaultMappingsConfig(config)
    ??? 在struts1.1以后,這個特例將會被廢棄:

    ??? defaultControllerConfig(config)為ControllerConfig通過getInitParameter(s)方法初始化如
    ??? 下幾個屬性:bufferSize,content,locale(true/false),maxFileSize,nocache(true/false)
    ??? ,multipartClass,tempDir。

    ??? defaultMessageResourcesConfig(config)為MessageResourcesConfig通過getInitParameter(s)
    ??? 方法初始化如下幾個屬性:application,factory,null(true/false)。

    ??? 其它的幾個方法就是獲取不同的對象,然后把它們相應的存儲到servlet中。關心如下:
    ??? ActionFormBeans=>FormBeanConfig,ActionForwards=>ForwardConfig,
    ??? ActionMappings=>ActionConfig。

    六、initModuleMessageResources(ModuleConfig config)
    ??? 通過存儲在ModuleConfig中的MessageResourcesConfig對象,逐個初始化MessageResource,
    ??? 然后再把初始化好的MessageResources存放到ServletContext中,attributeName為
    ??? MessageResourcesConfig.getKey() + ModuleConfig.getPrefix()。

    七、initModuleDataSources(ModuleConfig config)
    ??? 通過存儲在ModuleConfig中的DataSourceConfig對象,逐個初始化DataSource。然后對于每一個
    ??? DateSource通過BeanUtils.populate(ds, dscs[i].getProperties())方法初始化其屬性。再把初
    ??? 始化好的DateSource存放到ServletContext中,attributeName為
    ??? DataSourceConfig.getKey() + ModuleConfig.getPrefix()。同時也存放到名位dataSources的
    ??? FastHashMap中,key為DataSourceConfig.getKey()。

    ??? 這里還會根據(jù)生成的DateSource對象是否是GenericDataSource類型,如果是則調用
    ??? GenericDataSource.open()方法。GenericDataSource是一個非常簡單的數(shù)據(jù)庫連接池,它的
    ??? open()方法用來初始化連接池,生成最小數(shù)目的GenericConnection,這里的open()方法根據(jù)
    ??? String driver變量是否為null來判斷是否已經被初始化過。需要仔細說明的是getConnection()
    ??? 方法,它首先從連接池中取出GenericConnection對象,然后檢查其是否是可鏈接的,如果是就
    ??? 返回,否則繼續(xù)取出,同時activeCount-1。如果沒有取到,則會檢查當前可使用的
    ??? GenericConnection是否達到最大值(activeCount < maxCount),如果沒有,調用
    ??? createConnection()方法聲成一個新的GenericConnection,然后檢查其是否是可鏈接,如果可以
    ??? 則返回。returnConnection(GenericConnection conn)方法則是通過把GenericConnection放回到
    ??? 連接池,然后activeCount-1。

    ??? 這個方法中使用到了ServletContextWriter類,DateSource的log信息就通過這個類寫入。對這個
    ??? 類說明如下:
    ??? 它繼承自PrintWriter,而PrintWriter又繼承自Writer。Writer類所作的事情就是在同步的情況下
    ??? 調用abstract方法:abstract public void write(char cbuf[], int off, int len),這個方法
    ??? 將會根據(jù)調用者的需要由調用者實現(xiàn)。
    ??? PrintWriter則首先通過ensureOpen()方法檢驗這個類中是否有寫入的對象(Writer類或其子類),
    ??? 如果有則根據(jù)不同的情況調用這個寫入對象的write方法(out.write(....))。這個類的print(...)
    ??? 方法就是據(jù)不同的情況調用相應的write(...)方法。而println(...)與之的區(qū)別就是每次多寫入一
    ??? 個換行字符串。還有一個區(qū)別是println(...)會根據(jù)是否需要autoflush進行flush,而write(...)
    ??? 方法不會。
    ??? ServletContextWriter類的作用是把字符寫入ServletContext中。ServletContextWriter類方法中
    ??? 真正實現(xiàn)了write方法:
    ??? public void write(char c) {
    ??????? if (c == '\n')
    ??????????? flush();
    ??????? else if (c != '\r')
    ??????????? buffer.append(c);
    ??? }
    ??? public void flush() {
    ??????? if (buffer.length() > 0) {
    ??????????? context.log(buffer.toString());
    ??????????? buffer.setLength(0);
    ??????? }
    ??? }

    八、initModulePlugIns(moduleConfig)
    ??? 通過存儲在ModuleConfig中的PlugInConfig對象,逐個初始化PlugIn對象,存放到一個數(shù)組中,
    ??? 然后再把這個數(shù)組存放到ServletContext中,attributeName為
    ??? Globals.PLUG_INS_KEY + ModuleConfig.getPrefix()。

    ??? 對每一個生成的PlugIn對象通過
    ??? BeanUtils.populate(plugIns[i], plugInConfigs[i].getProperties())方法初始化其屬性。然后
    ??? 再把PlugInConfig對象存放到由其生成的PlugIn對象中。

    ??? 最后,通過plugIns[i].init(this, (ModuleConfig) config)初始化這個plugIn對象。

    九、初始化結束
    ??? 完成了這個初始化以后,會調用ModuleConfig.freeze()令這個ModuleConfig變得不可改變。然后
    ??? 會遍歷ServletConfig中的initParameterNames,如果有以"config/"開頭的,則通過這個parameter
    ??? 的值繼續(xù)初始化其它的ModuleConfig,且這個ModuleConfig的prefix為"config/"后的字符串。
    ???
    ??? 同樣調用如下方法:
    ??? initModuleMessageResources(moduleConfig);
    ??? initModuleDataSources(moduleConfig);
    ??? initModulePlugIns(moduleConfig);
    ??? moduleConfig.freeze();

    ??? 最后調用destroyConfigDigester()釋放內存。

    posted on 2006-09-13 20:24 ericli 閱讀(367) 評論(0)  編輯  收藏


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


    網站導航:
     
    主站蜘蛛池模板: 黄页网站免费观看| 性xxxx视频免费播放直播| 日韩精品免费一区二区三区| 亚洲国产精品成人精品软件| 久久免费看黄a级毛片| 亚洲沟沟美女亚洲沟沟| 亚洲国产精品免费在线观看| 亚洲精品欧洲精品| 久久不见久久见免费影院| 亚洲精品国产首次亮相| 亚洲精品无码久久毛片| 成人A毛片免费观看网站| 亚洲国产精品第一区二区| 91麻豆最新在线人成免费观看| 亚洲jizzjizz在线播放久| 全免费一级毛片在线播放| 边摸边吃奶边做爽免费视频网站| 亚洲精品尤物yw在线影院| 久久青草精品38国产免费| 亚洲一欧洲中文字幕在线| 国产禁女女网站免费看| 久久www免费人成看国产片| 亚洲最大成人网色| 青青青青青青久久久免费观看| 国产精品亚洲一区二区三区在线观看 | 国产人成亚洲第一网站在线播放| 夜夜爽免费888视频| 免费夜色污私人影院网站电影| 亚洲国产精品一区第二页| 色片在线免费观看| 麻豆安全免费网址入口| 亚洲国产AV无码专区亚洲AV| 成人无码区免费A片视频WWW| 美景之屋4在线未删减免费| 亚洲精品无码专区久久久| 中文字幕无码成人免费视频| www成人免费观看网站| 亚洲精品中文字幕乱码| 亚洲七七久久精品中文国产| h视频在线观看免费网站| 一级毛片在线免费视频|