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

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

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

    zhyiwww
    用平實的筆,記錄編程路上的點點滴滴………
    posts - 536,comments - 394,trackbacks - 0

    Struts 的資源文件時如何初始化的

    |-----------------------------------------------------------------------------------------------------|

    |????? ???????? ???????????? ?? ? 作者:zhyiwww ???????zhyiwww@163.com?????? ????????????? ???? |

    |???????????????????????????????????????????????????轉載請注明出處?????????????????????????????????????????? |
    |-----------------------------------------------------------------------------------------------------|

    分以下幾步來理解:

    [1] Web 應用如何知道使用的是 Struts

    我們知道,在 Web 工程的 /WEB-INF/ 目錄下面,我們有兩個配置文件

    Web.xml Struts-config.xml.

    一般情況下就只有一個 web.xml 文件,如果系統是用了 struts 技術的話,那么就會有 struts-config.xml 文件。

    [2] 系統是如何啟動和初始化 struts

    Web.xml 中有這么一段代碼:

    ? < servlet >

    ??? < servlet-name > action </ servlet-name >

    ??? < servlet-class > org.apache.struts.action.ActionServlet </ servlet-class >

    ??? < init-param >

    ????? < param-name > config </ param-name >

    ????? < param-value > /WEB-INF/struts-config.xml </ param-value >

    ??? </ init-param >

    ??? < init-param >

    ????? < param-name > debug </ param-name >

    ????? < param-value > 3 </ param-value >

    ??? </ init-param >

    ??? < init-param >

    ????? < param-name > detail </ param-name >

    ????? < param-value > 3 </ param-value >

    ??? </ init-param >

    ??? < load-on-startup > 0 </ load-on-startup >

    ? </ servlet >

    ? < servlet >

    ??? < servlet-name > startThread </ servlet-name >

    ??? < servlet-class > com.cgogo.ypindex.StartThread </ servlet-class >

    ??? < init-param >

    ??? < param-name > startParam </ param-name >

    ??? < param-value > 2 </ param-value >

    ??? </ init-param >

    ??? < load-on-startup > 1 </ load-on-startup >

    ? </ servlet > ?

    ? < servlet-mapping >

    ??? < servlet-name > action </ servlet-name >

    ??? < url-pattern > *.do </ url-pattern >

    ? </ servlet-mapping >

    web.xml 中會配置 struts 的中央控制器類。 Web.xml 配置文件的初始化是由容器來實現載入和初始化的。如果你使用的是 tomcat 的話,那么就是由 tomcat 在啟動的時候會載入此 web.xml 文件,也就為此 web 應用創建了一個 web Context, context 也就是你 Web 應用的訪問入口。

    載入中央控制器 org.apache.struts.action.ActionServlet ,這是一個 Servlet, 那么,其就要進行 servlet 的初始化操作。此 action 是如何對 Struts 系統進行初始化的呢?

    [3] init()-- ActionServlet 如何初始化 Struts 系統?

    看一下 ActionServlet 的源代碼:

    我們知道,在一個 Servlet 中,在其啟動的時候,首先要執行 init() 方法,那么我們先來看一下 actionServlet init() 方法的源代碼:

    ??? /**

    ???? * <p>Initialize this servlet.? Most of the processing has been factored into

    ???? * support methods so that you can override particular functionality at a

    ???? * fairly granular level.</p>

    ???? *

    ???? * @exception ServletException if we cannot configure ourselves correctly

    ???? */

    ?? ?public void init() throws ServletException {

    ?

    ??????? // Wraps the entire initialization in a try/catch to better handle

    ??????? // unexpected exceptions and errors to provide better feedback

    ??????? // to the developer

    ??????? try {

    (1)????? initInternal();

    (2)????? initOther();

    (3)????? initServlet();

    ???

    ??????????? getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this);

    (4)????? initModuleConfigFactory();

    ??????????? // Initialize modules as needed

    ??????????? ModuleConfig moduleConfig = initModuleConfig("", config);

    (5)????? initModuleMessageResources(moduleConfig);

    (6)????? initModuleDataSources(moduleConfig);

    (7)????? initModulePlugIns(moduleConfig);

    ??????????? moduleConfig.freeze();

    (8)????? 初始化配置參數

    ??????????? Enumeration names = getServletConfig().getInitParameterNames();

    ??????????? while (names.hasMoreElements()) {

    ??????????????? String name = (String) names.nextElement();

    ??????????????? if (!name.startsWith("config/")) {

    ?????????????? ?????continue;

    ??????????????? }

    ??????????????? String prefix = name.substring(6);

    ??????????????? moduleConfig = initModuleConfig

    ??????????????????? (prefix, getServletConfig().getInitParameter(name));

    ??????????????? initModuleMessageResources(moduleConfig);

    ??????????????? initModuleDataSources(moduleConfig);

    ??????????????? initModulePlugIns(moduleConfig);

    ??????????????? moduleConfig.freeze();

    ??????????? }

    ???

    ??????????? this.initModulePrefixes(this.getServletContext());

    ???

    ??????????? this.destroyConfigDigester();

    ??????? } catch (UnavailableException ex) {

    ??????????? throw ex;

    ??????? } catch (Throwable t) {

    ?

    ??????????? // The follow error message is not retrieved from internal message

    ??????????? // resources as they may not have been able to have been

    ??????????? // initialized

    ??????????? log.error("Unable to initialize Struts ActionServlet due to an "

    ??????????????? + "unexpected exception or error thrown, so marking the "

    ??????????????? + "servlet as unavailable.? Most likely, this is due to an "

    ??????????????? + "incorrect or missing library dependency.", t);

    ??????????? throw new UnavailableException(t.getMessage());

    ??????? }???

    }

    ?

    先來看一下初始化( 1 )的部分 initInternal()

    ?

    [4] ? initInternal()-- 內部資源文件的初始化

    initInternal() 就是實現內部資源文件的初始化的,也就是轉為 Struts 系統本身提供的以下錯誤信息提示等文字的國際化實現的。我們看一下源代碼是如何實現的:

    ??? /**

    ???? * <p> Initialize our internal MessageResources bundle. </p>

    ???? *

    ???? * @exception ServletException if we cannot initialize these resources

    ???? */

    ??? protected void initInternal() throws ServletException {

    ?

    ??????? // : FIXME : Document UnavailableException

    ?

    ??????? try {

    ??????????? internal = MessageResources.getMessageResources( internalName );

    ??????? } catch (MissingResourceException e) {

    ??????????? log.error( "Cannot load internal resources from '" + internalName + "'" ,

    ??????????????? e);

    ??????????? throw new UnavailableException

    ??????????????? ( "Cannot load internal resources from '" + internalName + "'" );

    ??????? }

    ?

    }

    Struts 根據配置文件的名字得到一個資源文件。

    internalName 就是內部資源文件的名稱,其在 actionServlet 中定義:

    ??? /**

    ???? * <p> The Java base name of our internal resources. </p>

    ???? * @since Struts 1.1

    ???? */

    ??? protected String internalName = "org.apache.struts.action.ActionResources" ;

    取得后的對象是一個 MessageResources 的對象,保存在 internal 中,

    ??? /**

    ???? * <p>The resources object for our internal resources.</p>

    ???? */

    ??? protected MessageResources internal = null;

    經過此初始化后, internal 就不在是 null 了。

    至此就實現完成了內部資源文件的初始化。如果出現了異常的話,那么系統就捕捉到。

    ?

    然后,系統就開始初始化其它的配置,即( 2 initOther();

    ?

    [5] initOther()-- 如何初始化其他的配置的?

    ??? /**

    ???? * <p>Initialize other global characteristics of the controller servlet.</p>

    ???? *

    ???? * @exception ServletException if we cannot initialize these resources

    ???? */

    ??? protected void initOther() throws ServletException {

    ?

    ??????? String value = null;

    ??????? value = getServletConfig().getInitParameter("config");

    ??????? if (value != null) {

    ??????????? config = value;

    ??????? }

    ?

    ??????? // Backwards compatibility for form beans of Java wrapper classes

    ??????? // Set to true for strict Struts 1.0 compatibility

    ??????? value = getServletConfig().getInitParameter("convertNull");

    ??????? if ("true".equalsIgnoreCase(value)

    ??????????? || "yes".equalsIgnoreCase(value)

    ??????????? || "on".equalsIgnoreCase(value)

    ??????? ????|| "y".equalsIgnoreCase(value)

    ??????????? || "1".equalsIgnoreCase(value)) {

    ?

    ??????????? convertNull = true;

    ??????? }

    ?

    ??????? if (convertNull) {

    ??????????? ConvertUtils.deregister();

    ??????????? ConvertUtils.register(new BigDecimalConverter(null), BigDecimal.class);

    ??????????? ConvertUtils.register(new BigIntegerConverter(null), BigInteger.class);

    ??????????? ConvertUtils.register(new BooleanConverter(null), Boolean.class);

    ??????????? ConvertUtils.register(new ByteConverter(null), Byte.class);

    ?? ?????????ConvertUtils.register(new CharacterConverter(null), Character.class);

    ??????????? ConvertUtils.register(new DoubleConverter(null), Double.class);

    ??????????? ConvertUtils.register(new FloatConverter(null), Float.class);

    ??????????? ConvertUtils.register(new IntegerConverter(null), Integer.class);

    ??????????? ConvertUtils.register(new LongConverter(null), Long.class);

    ??????????? ConvertUtils.register(new ShortConverter(null), Short.class);

    ??????? }

    ?

    }

    然后就執行( 3 initServlet();

    ?

    [6] ? initServlet()-- 如何初始化 servlet

    這個初始化主要是初始化 servlet 的,哪些 servlet 呢?就是我們在 web.xml 中配置的那些需要在 web application 初始化時就栽入系統的 servlet

    這是一個復雜的過程:

    ?

    我的理解:

    ?????? 這部分代碼就執行一次,僅在初始化的時候執行一次。

    ?????? ??? /**

    ???? * <p>Initialize the servlet mapping under which our controller servlet

    ???? * is being accessed.? This will be used in the <code>&html:form&gt;</code>

    ???? * tag to generate correct destination URLs for form submissions.</p>

    ???? *

    ???? * @throws ServletException if error happens while scanning web.xml

    ???? */

    ??? protected void initServlet() throws ServletException {

    ?

    ??????? // Remember our servlet name

    ?????? // 這里保存當前的servlet名字,保存在actionServletservletName屬性中

    ??????? this.servletName = getServletConfig().getServletName();

    ?

    ??????? // Prepare a Digester to scan the web application deployment descriptor

    ?????????????

    ??????? Digester digester = new Digester();

    ??????? digester.push(this);

    ??????? digester.setNamespaceAware(true);

    ??????? digester.setValidating(false);

    ?

    ??????? // Register our local copy of the DTDs that we can find

    ??????? for (int i = 0; i < registrations.length; i += 2) {

    ??????????? URL url = this.getClass().getResource(registrations[i+1]);

    ??????????? if (url != null) {

    ??????????????? digester.register(registrations[i], url.toString());

    ??????????? }

    ??????? }

    ?

    ??????? // Configure the processing rules that we need

    ??????? digester.addCallMethod("web-app/servlet-mapping",

    ?????????????????????????????? "addServletMapping", 2);

    ??????? digester.addCallParam("web-app/servlet-mapping/servlet-name", 0);

    ??????? digester.addCallParam("web-app/servlet-mapping/url-pattern", 1);

    ?

    ??????? // Process the web application deployment descriptor

    ??????? if (log.isDebugEnabled()) {

    ??????????? log.debug("Scanning web.xml for controller servlet mapping");

    ??????? }

    ?

    ? ??// 取得當前的配置文件???

    InputStream input =

    ??????????? getServletContext().getResourceAsStream("/WEB-INF/web.xml");

    ?

    ??????? if (input == null) {

    ??????????? log.error(internal.getMessage("configWebXml"));

    ??????????? throw new ServletException(internal.getMessage("configWebXml"));

    ??????? }

    ?

    ??????? try {

    ???????? ???// 解析當前配置文件

    digester.parse(input);

    ?

    ??????? } catch (IOException e) {

    ??????????? log.error(internal.getMessage("configWebXml"), e);

    ??????????? throw new ServletException(e);

    ?

    ??????? } catch (SAXException e) {

    ??????????? log.error(internal.getMessage("configWebXml"), e);

    ??????????? throw new ServletException(e);

    ?

    ??????? } finally {

    ??????????? try {

    ??????????????? // 解析完畢,關閉輸入

    input.close();

    ??????????? } catch (IOException e) {

    ??????????????? log.error(internal.getMessage("configWebXml"), e);

    ??? /**???????????

    如果有異常,當前部進行處理,而是留給他的調用者來處理。其實是當前的調用部分沒有處理的能力。我們可以這樣理解,假設你想在出現了這類異常異常的地方給用戶一個提示,但是在我們封裝功能實現的時候,我們并不知道誰會來調用,所以我們只有把異常拋出,讓調用者自己去處理。

    ??? 這一點也許不太好理解,不過,如果理解了,可能你就能夠靈活的使用異常了。

    */

    throw new ServletException(e);

    ??????????? }

    ??????? }

    ?

    ??????? // Record a servlet context attribute (if appropriate)

    ??????? if (log.isDebugEnabled()) {

    ??????????? log.debug("Mapping for servlet '" + servletName + "' = '" +

    ??????????????? servletMapping + "'");

    ??????? }

    ?

    ??????? if (servletMapping != null) {

    ??????????? getServletContext().setAttribute(Globals.SERVLET_KEY, servletMapping);

    ??????? }

    ?

    ??? }

    [7] 初始化其他模塊

    (1) ? 初始化工廠

    ??????????? getServletContext().setAttribute( Globals . ACTION_SERVLET_KEY , this );

    ??????????? initModuleConfigFactory();

    (2) ? 初始化資源模塊

    ??????????? // Initialize modules as needed

    ??????????? ModuleConfig moduleConfig = initModuleConfig( "" , config );

    ? ?????????? initModuleMessageResources(moduleConfig);

    (3) ? 初始化數據源配置模塊

    ??????????? initModuleDataSources(moduleConfig);

    (4) ? 初始化 PlugIn 模塊

    ??????????? initModulePlugIns(moduleConfig);

    ??????????? moduleConfig.freeze();

    [8] ? 初始化參數

    ??????????? Enumeration names = getServletConfig().getInitParameterNames();

    ??????????? while (names.hasMoreElements()) {

    ??????????????? String name = (String) names.nextElement();

    ??????????????? if (!name.startsWith("config/")) {

    ??????????????????? continue;

    ??????????????? }

    ??????????????? String prefix = name.substring(6);

    ??????????????? moduleConfig = initModuleConfig

    ??????????????????? (prefix, getServletConfig().getInitParameter(name));

    ??????????????? initModuleMessageResources(moduleConfig);

    ??????????????? initModuleDataSources(moduleConfig);

    ??????????????? initModulePlugIns(moduleConfig);

    ??????????????? moduleConfig.freeze();

    ??????????? }

    [9] ? 我也不知道做什么用的 ???

    ??????????? this .initModulePrefixes( this .getServletContext());

    ???

    ??????????? this .destroyConfigDigester();

    以上就是Struts的初始化流程。

    [10] ???????? 部分模塊的詳細實現:

    a. ????? 工廠的初始化如何實現的:

    ??? /**

    ???? * <p>Initialize the factory used to create the module configuration.</p>

    ???? * @since Struts 1.2

    ???? */

    protected void initModuleConfigFactory(){

    /**

    這個部分的代碼就是取得參數。

    這個參數你可以自己擴展你的模塊實現工廠。但是一般都沒有自己去做。

    所以一般都使用的默認的工廠初始化配置。

    */

    ??????? String configFactory = getServletConfig().getInitParameter("configFactory");

    /**

    下面的代碼,只有你做了自己的配置才會有效。否則一般是不執行的。

    */

    ??????? if (configFactory != null) {

    /**

    設置此工廠,并把其參數存入到 ModuleConfigFactory.factoryClass 屬性中。

    此部分可以看 ModuleConfigFactory 的代碼。 ModuleConfigFactory 是一個

    */

    ??????????? ModuleConfigFactory.setFactoryClass(configFactory);

    ??????? }

    ??? }

    b. ????? 資源模塊式如何初始化的

    // 調用的部分

    protected String config = "/WEB-INF/struts-config.xml";

    ------------------------------------------------------------------??????????

    ModuleConfig moduleConfig = initModuleConfig("", config);

    initModuleMessageResources(moduleConfig);

    ?????? // 實現的部分:

    ??? protected void initModuleMessageResources (ModuleConfig config)

    ??????? throws ServletException {

    ?????? ?????? /**

    ?????? struts-config.xml 中的資源文件配置,你可能配置了多個資源,所以此處取得是一個數組

    */

    ??????? MessageResourcesConfig mrcs[] = config.findMessageResourcesConfigs();

    ?

    ??????? for (int i = 0; i < mrcs.length; i++) {

    ??????????? if ((mrcs[i].getFactory() == null)

    ??????????????? || (mrcs[i].getParameter() == null)) {

    ?????????????? ?continue;

    ??????????? }

    ??????????? if (log.isDebugEnabled()) {

    ??????????????? log.debug(

    ??????????????????? "Initializing module path '"

    ??????????????????????? + config.getPrefix()

    ??????????????????????? + "' message resources from '"

    ?????????????? ?????????+ mrcs[i].getParameter()

    ??????????????????????? + "'");

    ??????????? }

    /**

    ?????? ??? protected String factory =

    ??????? "org.apache.struts.util.PropertyMessageResourcesFactory";

    就是返回的這個值,如果你沒有做其他的設置的話。

    一般情況下,我們都用得是默認的

    */

    ??????????? String factory = mrcs[i].getFactory();

    /**

    ?????? 此處對每一個資源配置文件都回去創建一個工廠

    */

    ??????????? MessageResourcesFactory.setFactoryClass(factory);

    ??????????? MessageResourcesFactory factoryObject =

    ??????????????? MessageResourcesFactory.createFactory();

    ??????????? factoryObject.setConfig(mrcs[i]);

    ??????????? MessageResources resources =

    ??????????????? factoryObject.createResources(mrcs[i].getParameter());

    ??????????? resources.setReturnNull(mrcs[i].getNull());

    ?? ?????????resources.setEscape(mrcs[i].isEscape());

    ?

    ?????? /**

    這一部分非常重要。

    我們之所以能夠直接調用,就是因為,初始化后,我們就把此 resources 放到了其對應的當前應用的屬性值里面了。之后我們就可以直接調用了。
    ?????? */

    ??????????? getServletContext().setAttribute(

    ??????????????? mrcs[i].getKey() + config.getPrefix(),

    ??????????????? resources);

    ??????? }

    ?

    ??? }

    c. ????? 數據模塊是如何初始化的

    ==========================================================

    // 調用部分

    initModuleDataSources(moduleConfig);

    ?

    // 實現部分:

    /**

    ???? * <p>Initialize the data sources for the specified module.</p>

    ???? *

    ???? * @param config ModuleConfig information for this module

    ???? *

    ???? * @exception ServletException if initialization cannot be performed

    ???? * @since Struts 1.1

    ???? */

    ??? protected void initModuleDataSources(ModuleConfig config) throws ServletException {

    ?

    ??????? // :FIXME: Document UnavailableException?

    ?

    ??????? if (log.isDebugEnabled()) {

    ??????????? log.debug("Initializing module path '" + config.getPrefix() +

    ??????????????? "' data sources");

    ??????? }

    ?

    ??????? ServletContextWriter scw =

    ??????????? new ServletContextWriter(getServletContext());

    /**

    因為你可能配置了多個數據源,所以此處返回的是一個數組
    */

    ??????? DataSourceConfig dscs[] = config.findDataSourceConfigs();

    ?? ?// 處理沒有配置數據源的情況

    if (dscs == null) {

    dscs = new DataSourceConfig[0];

    ??????? }

    /**

    ?????? ??? /**

    ???? * <p>The JDBC data sources that has been configured for this module,

    ???? * if any, keyed by the servlet context attribute under which they are

    ???? * stored.</p>

    ???? */

    protected FastHashMap dataSources = new FastHashMap();

    這是一個加工過的 HashMap ,又不同的工作模式

    ?

    */

    ?

    ??????? dataSources.setFast(false);

    ??????? for (int i = 0; i < dscs.length; i++) {

    ??????????? if (log.isDebugEnabled()) {

    ??????????????? log.debug("Initializing module path '" + config.getPrefix() +

    ??????????????????? "' data source '" + dscs[i].getKey() + "'");

    ??????????? }

    ??????????? DataSource ds = null;

    ??????????? try {

    ?????? ???/**

    */

    ?? ds = (DataSource)

    ??????????????????? RequestUtils.applicationInstance(dscs[i].getType());

    ??????????????? BeanUtils.populate(ds, dscs[i].getProperties());

    ??????????????? ds.setLogWriter(scw);

    ?

    ??????????? } catch (Exception e) {

    ??????????? ????log.error(internal.getMessage("dataSource.init", dscs[i].getKey()), e);

    ??????????????? throw new UnavailableException

    ??????????????????? (internal.getMessage("dataSource.init", dscs[i].getKey()));

    ??????????? }

    /**

    ?????? 這一個部分很重要。

    ?????? 把初始化后的數據源放入到 servlet 的屬性中,所以我們才可以通過 struts 的對應屬性直接訪問。

    ? protected String key = Globals.DATA_SOURCE_KEY;

    所以,我們可以通過 Globals.DATA_SOURCE_KEY 屬性的值來取得其配制后的數據源。

    如果多個的話,可以通過數據源的參數 ID 來配置和調用。

    */

    ??????????? getServletContext().setAttribute

    ??????????????? (dscs[i].getKey() + config.getPrefix(), ds);

    ??????????? dataSources.put(dscs[i].getKey(), ds);

    ??????? }

    ?

    ??????? dataSources.setFast(true);

    ?

    ??? }

    ?

    至此,Struts系統初始化完畢。

    ?

    ?

    ?

    ?

    ?



    |----------------------------------------------------------------------------------------|
                               版權聲明  版權所有 @zhyiwww
                引用請注明來源 http://m.tkk7.com/zhyiwww   
    |----------------------------------------------------------------------------------------|
    posted on 2006-12-25 16:47 zhyiwww 閱讀(3354) 評論(1)  編輯  收藏 所屬分類: j2ee

    FeedBack:
    # re: Struts的資源文件時如何初始化的--struts源碼學習
    2007-01-25 13:49 | bearshy
    頂  回復  更多評論
      
    主站蜘蛛池模板: 亚洲今日精彩视频| 日韩激情无码免费毛片| 日本免费污片中国特一级| 成人午夜影视全部免费看| 色www免费视频| 免费在线观看一区| 一区在线免费观看| 中国国产高清免费av片| 国产自国产自愉自愉免费24区| 拍拍拍无挡免费视频网站| 免费在线中文日本| 亚洲精品视频在线免费| 69xx免费观看视频| 91在线视频免费播放| 成年女性特黄午夜视频免费看| 在线精品免费视频| 免费人成在线观看播放国产| 亚洲性久久久影院| 亚洲福利在线视频| 亚洲人成免费网站| 亚洲日韩久久综合中文字幕| 特黄aa级毛片免费视频播放| 久久久久久噜噜精品免费直播 | 亚洲国产精品狼友中文久久久| 亚洲AV无码一区二三区| 亚洲精品国产精品乱码视色 | 亚洲AV日韩精品一区二区三区| 亚洲欧洲国产成人综合在线观看| 亚洲精品国产精品乱码不卡√| 亚洲精品偷拍无码不卡av| 亚洲欧美日韩一区二区三区在线| 看免费毛片天天看| 久草免费福利视频| 免费无码A片一区二三区| 亚洲乱亚洲乱少妇无码| 亚洲人成在线电影| 亚洲熟女综合一区二区三区| 一本一道dvd在线观看免费视频| 91香蕉国产线观看免费全集| 女人18毛片水真多免费看| 国产亚洲美日韩AV中文字幕无码成人|