一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - struts1之ActionServlet詳解_動力節點Java學院整理

struts1之ActionServlet詳解_動力節點Java學院整理

2020-12-26 14:31lfsf802 Java教程

這篇文章主要介紹了struts1之ActionServlet詳解,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

在web.xml中我們除了配置actionservlet還配置了一些初始化參數信息,首先我們看第一個config參數,這里配置的是/web-inf/struts-config.xml,因為要下面傳遞一個這樣一個配置信息,這個xml文件名是struts1標準的名字,所以這里這個初始化信息完全可以刪除,如果不用這個標準名稱這里就必須要在這里配置?,F在我們配置的是標準名字,所以我們可以刪除,這是為什么呢?這里要看actionservlet源代碼才可以。

struts1之ActionServlet詳解_動力節點Java學院整理

從圖片上我們能看到actionservlet中已經寫好了默認的config信息了,就是標準名字。所以這里刪除也是可以的。
在看下面的debug和detail參數,這兩個參數信息是有關日志信息級別的設置,主要關于解析配置文件/web-inf/struts-config.xml級別的初始化參數。這里這兩個參數可以完全去掉也不影響。

最后還有一個load-on-startup配置,這個是初始化servlet級別的初始化信息,這個參數如果大于等于0就是說明在服務器一啟動就把servlet初始化,也就是調用actionservlet的init方法,這個也可以到actionservlet的源代碼中去查找。

當actionservlet初始化的時候就會讀取/web-inf/struts-config.xml信息到內存中,讀到內存是以什么樣的形式展現的呢?我們現在可以看一下以前博客的那個mvc實例,那里面讀取配置文件中的信息是以actionmapping的形式展現的。另外servlet-mapping的配置就不講解了,這個都知道就是匹配url路徑的,當遇到url-pattern的路徑時候就會實例化actionservlet。

通過這篇文章我們知道了當我們請求的時候actionservlet是怎樣實例化的,也知道為什么我們要配置web.xml信息了。那么我們為什么要配置/web-inf/struts-config.xml文件,actionservlet是如何傳遞請求的,如何和actionform、actionmapping、action等交互的最終完成用戶請求的呢?

我們先從actionservlet源代碼的init方法開始。因為actionservlet就是一個servlet,它也是具有典型的那幾個方法init、doget、dopost等方法。既然是初始化,那么我們就要看init方法。init方法的源代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/**
   * <p>initialize this servlet. most of the processing has been factored into
   * support methods so that you can overrideparticular functionality at a
   * fairly granular level.</p>
   *
   * @exception servletexception if we cannotconfigure ourselves correctly
   */
  publicvoidinit() throwsservletexception {
  
    // wraps the entire initialization in a try/catch tobetter handle
    // unexpected exceptions and errors to provide better feedback
    // to the developer
    try {
      initinternal();
      initother();
      initservlet();
   
      getservletcontext().setattribute(globals.action_servlet_key, this);
      initmoduleconfigfactory();
      // initialize modules as needed
      moduleconfig moduleconfig =initmoduleconfig("", config);
      initmodulemessageresources(moduleconfig);
      initmoduledatasources(moduleconfig);
      initmoduleplugins(moduleconfig);
      moduleconfig.freeze();
   
      enumeration names =getservletconfig().getinitparameternames();
      while (names.hasmoreelements()) {
        string name = (string)namesnextelement();
        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());
   
      thisdestroyconfigdigester();
    } 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
      logerror("unable to initialize struts actionservlet due to an "
        + "unexpected exception or error thrown, so marking the "
        + "servlet as unavailable. mostlikely, this is due to an "
        + "incorrect or missing library dependency.", t);
      throw new unavailableexception(t.getmessage());
    }  
}

在解釋這段代碼的流程和意思之前,有必要說一句,就是當我們在eclipse里面看代碼的時候,尤其是看一段生疏的很長的代碼的時候,希望能夠經常使用ctrl鍵(多余的不解釋)。

下面開始講解這段代碼的流程和具體每一步的含義,如果有不正確的地方,希望指正。

首先映入眼簾的是initinternal()方法。這個方法的實現代碼是:

代碼段一:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
   * <p>initialize our internal messageresourcesbundle</p>
   *
   * @exception servletexception if we cannotinitialize these resources
   */
  protectedvoidinitinternal() throwsservletexception {
  
    // :fixme: document unavailableexception
  
    try {
      internal = messageresourcesgetmessageresources(internalname);
    } catch (missingresourceexception e) {
      log.error("cannot load internal resources from '"+ internalname+ "'",
        e);
      throw new unavailableexception
        ("cannot load internal resources from '"+ internalname+ "'");
    }
  
}

代碼段二:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
   * create and return an instance of <code>messageresources</code> for the
   * created by the default <code>messageresourcesfactory</code>.
   *
   * @param config configuration parameterfor this message bundle.
   */
  publicsynchronizedstaticmessageresources getmessageresources(string config) {
  
    if (defaultfactory == null) {
      defaultfactory =messageresourcesfactory.createfactory();
    }
  
    return defaultfactory.createresources(config);
}

代碼段三:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
   * create and return a <code>messageresourcesfactory</code> instance ofthe
   * appropriate class, which can be used tocreate customized
   * <code>messageresources</code>instances if no such factory can be
   * created, return <code>null</code> instead
   */
  publicstaticmessageresourcesfactory createfactory(){
  
    // construct a new instance of the specified factory class
    try {
      if (clazz == null)
        clazz = requestutils.applicationclass(factoryclass);
      messageresourcesfactory factory =
        (messageresourcesfactory) clazz.newinstance();
      return (factory);
    } catch (throwable t) {
      log.error("messageresourcesfactory.createfactory",t);
      return (null);
    }
  
}

這個方法的具體作用就是初始化messageresources,具體實現是工廠模式,首先判斷defaultfactory是否存在,不存在則創建工廠,defaultfactory = messageresourcesfactory.createfactory(),在通過工廠創建資源類defaultfactory.createresources(config);存在則直接創建資源類。

initother()的方法,主要是初始化其它的配置,獲取我們自己的struts-config配置文件的路徑,而它的默認路徑就是web-inf/struts-config.xml,另外這個方法還會注冊一些轉換類的。具體源代碼是:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
   * <p>initialize other global characteristics ofthe controller servlet</p>
   *
   * @exception servletexception if we cannotinitialize these resources
   */
  protectedvoidinitother() throwsservletexception {
  
    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 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);
    }
  
}

initservlet()方法是利用digester讀取web.xml文件并且放到servletcontext中。具體實現源代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/**
 * <p>initialize the servlet mapping under which our controller servlet
 * is being accessed. this will be used in the <code>&html:form></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
  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()) {
    logdebug("mapping for servlet '" + servletname + "' = '" +
      servletmapping + "'");
  }
 
  if (servletmapping != null) {
    getservletcontext().setattribute(globals.servlet_key, servletmapping);
  }
 
}

首先說在說之前還是先講init方法的具體實現代碼寫出來以便大家方便閱讀和理解。

init源代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public void init() throws servletexception {
  
 try {
    //初始化資源類
   initinternal();
   //注冊轉換類
   initother();
   //利用digester讀取webxml文件并且將其放到servletcontext中
   initservlet();
   getservletcontext().setattribute(globals.action_servlet_key, this);
    
   initmoduleconfigfactory();
   moduleconfig moduleconfig = initmoduleconfig("", config);
   initmodulemessageresources(moduleconfig);
   initmoduledatasources(moduleconfig);
   initmoduleplugins(moduleconfig);
   moduleconfig.freeze();
 
   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) {
   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());
 }  
}

getservletcontext().setattribute(globals.action_servlet_key,this);這句話是將actionservlet實例將以globals.action_servlet_key作為key存入servletcontext中。

 這里的globals.action_servlet_key在actionservlet已經給出了聲明:

?
1
public static final string action_servlet_key= "org.apache.struts.action.action_servlet";

接下來initmoduleconfigfactory()方法,這個方法主要的作用是解析在web.xml中configfactory的text值。如果configfactory有配置,則將設置moduleconfigfactory中得factoryclass值,否則默認得為efaultmoduleconfigfactory。該方法其實宗旨是讓開發人員自己開發出moduleconfigfactory,從而得到自己所需要的moduleconfig類。因為我們的實例中沒有配置這個參數信息,所以我們這里的實例是要defalutmodelconfigfactory了。

代碼段一:

?
1
2
3
4
5
6
protected voidinitmoduleconfigfactory(){
    string configfactory =getservletconfig().getinitparameter("configfactory");
    if (configfactory != null) {
      moduleconfigfactory.setfactoryclass(configfactory);
    }
}

代碼段二:

?
1
2
3
4
public static void setfactoryclass(string factoryclass) {
    moduleconfigfactory.factoryclass = factoryclass;
    moduleconfigfactory.clazz = null;
  }

代碼段三:

?
1
2
3
protected static string factoryclass =
    "org.apache.struts.config.impl.defaultmoduleconfigfactory";
}

moduleconfig moduleconfig =initmoduleconfig("", config)方法是非常重要的,initmoduleconfig方法給strits-config里面的屬性初始化后放入moduleconfig對象里面去,放到moduleconfig對象里面去便于以后操作更快,因為它是文件流。

具體實現代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
protected moduleconfig initmoduleconfig(stringprefix, string paths)
    throws servletexception {
  
    // :fixme: document unavailableexception? (doesn't actually throw anything)
  
    if (log.isdebugenabled()) {
      log.debug(
        "initializing module path '"
          + prefix
          + "' configuration from '"
          + paths
          + "'");
    }
  
    // parse the configuration for this module
    moduleconfigfactory factoryobject= moduleconfigfactory.createfactory();
    moduleconfig config =factoryobject.createmoduleconfig(prefix);
  
    // configure the digester instance we will use
    digester digester =initconfigdigester();
  
    // process each specified resource path
    while (paths.length() > 0) {
      digester.push(config);
      string path = null;
      int comma = paths.indexof(',');
      if (comma >= 0) {
        path =paths.substring(0, comma).trim();
        paths =paths.substring(comma + 1);
      } else {
        path = pathstrim();
        paths = "";
      }
  
      if (pathlength() < 1){
        break;
      }
  
      this.parsemoduleconfigfile(digester,path);
    }
  
    getservletcontext().setattribute(
      globals.module_key +config.getprefix(),
      config);
  
  
    // force creation and registration of dynaactionformclass instances
    // for all dynamic form beans we wil be using
    formbeanconfig fbs[] =config.findformbeanconfigs();
    for (int i = 0; i < fbs.length; i++) {
      if (fbs[i].getdynamic()) {
        fbs[i].getdynaactionformclass();
      }
    }
  
    return config;
}

這里有必要解析一下這段代碼。首先得到繼承moduleconfigfactory的實現類,如果在initmoduleconfigfactory()中能設置factoryclass屬性,則能生成客戶化得factory,否則得到得是默認得defaultmoduleconfigfactory類,該工廠得到moduleconfigimpl類。然后調用initconfigdigester()該方法為解析配置文件做準備,初始化digest類(具體digest的初始化實現就不講解)。最后返回moduleconfig,而這時的moduleconfig里面封裝了所有的struts-config.xml中的信息。

最后的幾個方法就簡單說一下就行,不是非常難理解:

initmodulemessageresources(moduleconfig)方法是通過moduleconfig中的配置文件信息,創建messageresource對象.

initmoduledatasources(moduleconfig)方法是通過moduleconfig中的配置文件信息,創建datasource對象.   initmoduleplugins(moduleconfig)加載并初始化默認應用模塊的所有插件的。

moduleconfig.freeze()是將配置文件中的各個對象,設置成已配置狀態.

最后我們看到了,下面還有一段同上面代碼的循環代碼,這段代碼的主要意思就是當默認子應用模塊被成功初始化后,如果應用還包括其他子應用模塊,將重復流程,分別對其他子應用模塊進行初始化。這個也是很好理解的。

到此為止actionservlet就init完成。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美性欲 | 成人免费视频一区 | 激情影院免费观看 | 性做久久久久免费观看 | 国产高清国内精品福利 | 日韩一卡2卡3卡新区网站 | 国产小青蛙 | 女教师被女同学调教成脚奴 | 国色天香社区视频在线观看免费完整版 | 国产98在线 | 国产精品成人免费福利 | 精品国产美女AV久久久久 | 国产精品成人一区二区1 | 天天狠天天透 | 美女视频一区二区三区在线 | 五月色婷婷在线影院 | 精品欧美日韩一区二区三区 | 国产欧美一区二区成人影院 | 青丝视频免费版在线看 | 69japanese日本100| 国产一卡二卡3卡4卡四卡在线视频 | 暖暖视频免费观看视频中国.韩剧 | 99热在线免费观看 | 成人免费高清视频 | 亚欧毛片基地国产毛片基地 | 亚洲色图150p | www伊人| 成人国产精品 | 亚洲男女在线 | 青青成人福利国产在线视频 | 肉宠文很肉到处做1v1 | 深夜影院a | 97理伦 | 三级黄色图片 | 免费国产高清视频 | 日本在线观看免费高清 | 国产成人综合一区人人 | 日韩网新片免费 | 日本中文字幕一区二区高清在线 | 黑人破中国女人处 | 深夜福利免费在线观看 |