Heim >Java >javaLernprogramm >Detaillierte Erläuterung von Beispielen für ActionServlet in struts1

Detaillierte Erläuterung von Beispielen für ActionServlet in struts1

黄舟
黄舟Original
2017-09-05 11:31:201491Durchsuche

Dieser Artikel stellt hauptsächlich die detaillierte Erklärung von ActionServlet in struts1 vor. Der Herausgeber findet es ziemlich gut, ich werde es jetzt mit Ihnen teilen und als Referenz geben. Folgen wir dem Editor und werfen wir einen Blick darauf.

In web.xml konfigurieren wir zusätzlich zur Konfiguration von ActionServlet auch einige Initialisierungsparameter. Schauen wir uns zunächst den ersten Konfigurationsparameter an, der hier konfiguriert ist -INF/struts -config.xml, da diese Konfigurationsinformationen unten übergeben werden müssen. Der Name dieser XML-Datei ist der Standardname von struts1, sodass die Initialisierungsinformationen hier gelöscht werden können. es muss hier konfiguriert werden. Jetzt konfigurieren wir den Standardnamen, damit wir ihn löschen können. Warum ist das so? Hier müssen Sie sich den ActionServlet-Quellcode ansehen.

Auf dem Bild können wir sehen, dass die Standardkonfigurationsinformationen in ActionServlet geschrieben wurden, was der Standardname ist. Daher ist es hier auch möglich, es zu löschen.
Sehen Sie sich die Debug- und Detailparameter unten an. Diese beiden Parameterinformationen beziehen sich auf die Einstellungen der Protokollinformationsebene, hauptsächlich auf das Parsen der Initialisierungsparameter auf der Ebene der Konfigurationsdatei/WEB-INF/struts-config.xml. Diese beiden Parameter können hier ohne Auswirkung vollständig entfernt werden.

Schließlich gibt es eine Load-on-Startup-Konfiguration, bei der es sich um die Initialisierungsinformationen zum Initialisieren der Servlet-Ebene handelt. Wenn dieser Parameter größer oder gleich 0 ist, bedeutet dies, dass das Servlet sofort initialisiert wird Der Server wird gestartet, das heißt, die Init-Methode von ActionServlet wird aufgerufen. Dies ist auch im Quellcode von ActionServlet zu finden.

Wenn ActionServlet initialisiert wird, liest es die /WEB-INF/struts-config.xml-Informationen in den Speicher. In welcher Form wird der Speicher angezeigt? Wir können nun einen Blick auf die MVC-Instanz aus dem vorherigen Blog werfen, in der die in der Konfigurationsdatei gelesenen Informationen in Form von Actionmapping angezeigt werden. Darüber hinaus wird die Konfiguration der Servlet-Zuordnung nicht erläutert. Wir alle wissen, dass sie mit dem URL-Pfad übereinstimmt und das Actionservlet instanziiert wird.

Durch diesen Artikel erfahren wir, wie ActionServlet instanziiert wird, wenn wir es anfordern, und warum wir web.xml-Informationen konfigurieren müssen. Warum konfigurieren wir also die Datei /WEB-INF/struts-config.xml? Wie interagiert ActionServlet mit ActionForm, ActionMapping, Action usw., um letztendlich Benutzeranfragen abzuschließen?

Beginnen wir mit der Init-Methode des ActionServlet-Quellcodes. Da ActionServlet ein Servlet ist, verfügt es auch über die typischen Methoden init, doget, dopost und andere. Da es sich um eine Initialisierung handelt, müssen wir uns die Init-Methode ansehen. Der Quellcode der Init-Methode lautet wie folgt:


/** 
   * <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()); 
    }   
}

Bevor wir den Ablauf und die Bedeutung dieses Codes erklären, müssen wir Folgendes sagen: Ich hoffe, dass ich beim Lesen von Code, insbesondere beim Betrachten eines langen und unbekannten Codeabschnitts, die Strg-Taste häufig verwenden kann (keine unnötigen Erklärungen).

Im Folgenden wird der Prozess dieses Codes und die spezifische Bedeutung der einzelnen Schritte erläutert. Wenn etwas falsch ist, hoffe ich, es zu korrigieren.

Das erste, was in Sicht kommt, ist die initInternal()-Methode. Der Implementierungscode dieser Methode lautet:

Codesegment eins:


/** 
   * <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 &#39;"+ internalName+ "&#39;", 
        e); 
      throw new UnavailableException 
        ("Cannot load internal resources from &#39;"+ internalName+ "&#39;"); 
    } 
  
}

Codesegment zwei:


/** 
   * 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); 
}

Codesegment drei:


/** 
   * 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); 
    } 
  
}

Die spezifische Funktion dieser Methode besteht darin, Initialisieren Sie MessageResources. Stellen Sie zunächst fest, ob die defaultFactory vorhanden ist. Erstellen Sie dann die Factory-Ressourcenklasse defaultFactory.createFactory. ; falls vorhanden, erstellen Sie die Ressourcenklasse direkt.

Die Methode initOther() dient hauptsächlich dazu, andere Konfigurationen zu initialisieren und den Pfad unserer eigenen Struts-Config-Konfigurationsdatei abzurufen. Der Standardpfad ist außerdem web-inf/struts-config.xml , diese Methode registriert auch einige Konvertierungsklassen. Der spezifische Quellcode lautet:


/** 
   * <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); 
    } 
  
}

Die initServlet()-Methode verwendet den Digester, um die Datei web.xml zu lesen und in den ServletContext einzufügen. Spezifischer Implementierungsquellcode:


/** 
 * <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 &#39;" + servletName + "&#39; = &#39;" + 
      servletMapping + "&#39;"); 
  } 
 
  if (servletMapping != null) { 
    getServletContext().setAttribute(Globals.SERVLET_KEY, servletMapping); 
  } 
 
}

Bevor ich darüber spreche, möchte ich zunächst über den spezifischen Implementierungscode der Init-Methode sprechen und ihn schreiben so dass jeder es leicht lesen und verstehen kann.

Init-Quellcode:


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); Dieser Satz ist das ActionServlet Die Instanz wird im Servletcontext mit Globals.ACTION_SERVLET_KEY als Schlüssel gespeichert.

Der Globals.ACTION_SERVLET_KEY hier wurde in ActionServlet deklariert:


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了。

代码段一:


protected voidinitModuleConfigFactory(){ 
    String configFactory =getServletConfig().getInitParameter("configFactory"); 
    if (configFactory != null) { 
      ModuleConfigFactory.setFactoryClass(configFactory); 
    } 
}

代码段二:


public static void setFactoryClass(String factoryClass) { 
    ModuleConfigFactory.factoryClass = factoryClass; 
    ModuleConfigFactory.clazz = null; 
  }

代码段三:


protected static String factoryClass = 
    "org.apache.struts.config.impl.DefaultModuleConfigFactory"; 
}

ModuleConfig moduleConfig =initModuleConfig("", config)方法是非常重要的,initModuleConfig方法给strits-config里面的属性初始化后放入moduleConfig对象里面去,放到moduleConfig对象里面去便于以后操作更快,因为它是文件流。

具体实现代码:


protected ModuleConfig initModuleConfig(Stringprefix, String paths) 
    throws ServletException { 
  
    // :FIXME: Document UnavailableException? (Doesn&#39;t actually throw anything) 
  
    if (log.isDebugEnabled()) { 
      log.debug( 
        "Initializing module path &#39;" 
          + prefix 
          + "&#39; configuration from &#39;" 
          + paths 
          + "&#39;"); 
    } 
  
    // 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(&#39;,&#39;); 
      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完成。

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung von Beispielen für ActionServlet in struts1. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn