>  기사  >  Java  >  Struts1의 ActionServlet 코드 공유

Struts1의 ActionServlet 코드 공유

巴扎黑
巴扎黑원래의
2017-09-06 09:27:201580검색

이 기사는 주로 struts1의 ActionServlet에 대한 자세한 설명을 소개합니다. 편집자는 이것이 꽤 좋다고 생각합니다. 이제 공유하고 참고하겠습니다. 편집기를 따라 살펴보겠습니다

web.xml에서는 ActionServlet 구성 외에도 일부 초기화 매개변수 정보도 구성합니다. 먼저 여기서 구성되는 첫 번째 구성 매개변수는 /WEB-INF/struts입니다. -config.xml , 아래에 이러한 구성 정보를 전달해야 하기 때문에 이 xml 파일의 이름은 struts1의 표준 이름이므로, 이 표준 이름을 사용하지 않는 경우 여기의 초기화 정보는 완전히 삭제될 수 있습니다. 여기에서 구성했습니다. 이제 표준 이름을 구성했으니 삭제할 수 있습니다. 왜 그럴까요? 여기에서 ActionServlet 소스 코드를 살펴봐야 합니다.

사진을 보면 표준명인 ActionServlet에 기본 config 정보가 쓰여져 있는 것을 알 수 있습니다. 따라서 여기서 삭제도 가능합니다.
아래 디버그 및 세부 매개변수를 살펴보세요. 이 두 매개변수 정보는 로그 정보 수준의 설정과 관련이 있으며 주로 구성 파일/WEB-INF/struts-config.xml 수준에서 초기화 매개변수를 구문 분석하는 것과 관련됩니다. 여기서 이 두 매개변수는 아무런 효과 없이 완전히 제거될 수 있습니다.

마지막으로 load-on-startup 구성이 있습니다. 서블릿 레벨을 초기화하기 위한 초기화 정보입니다. 이 매개변수가 0보다 크거나 같으면 서버가 시작되자마자 서블릿이 초기화된다는 의미입니다. 즉, ActionServlet의 init 메소드가 호출됩니다. 이는 ActionServlet의 소스 코드로 이동하여 찾을 수도 있습니다.

ActionServlet이 초기화되면 /WEB-INF/struts-config.xml 정보를 메모리로 읽어들입니다. 메모리는 어떤 형태로 표시되나요? 이제 이전 블로그의 mvc 인스턴스를 살펴보겠습니다. 여기서 구성 파일에서 읽은 정보가 Actionmapping 형식으로 표시됩니다. 또한 servlet-mapping의 구성은 설명되지 않습니다. 우리 모두는 url-pattern 경로가 발견되면 Actionservlet이 인스턴스화된다는 것을 알고 있습니다.

이 기사를 통해 ActionServlet을 요청할 때 인스턴스화되는 방법과 web.xml 정보를 구성해야 하는 이유를 알 수 있습니다. 그러면 /WEB-INF/struts-config.xml 파일을 구성하는 이유는 무엇입니까? ActionServlet은 어떻게 요청을 전송합니까? 최종적으로 사용자 요청을 완료하기 위해 ActionForm, ActionMapping, Action 등과 어떻게 상호 작용합니까?

ActionServlet 소스 코드의 init 메소드부터 시작해 보겠습니다. ActionServlet은 서블릿이기 때문에 일반적인 메소드 init, doget, dopost 및 기타 메소드도 가지고 있습니다. 초기화이므로 init 메소드를 살펴봐야 합니다. Init 메소드의 소스코드는 다음과 같습니다.


/** 
   * <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() 메서드입니다. 이 메소드의 구현 코드는 다음과 같습니다. 초기화는 MessageResources이며, 구체적인 구현은 팩토리 모드입니다. 먼저 defaultFactory가 존재하는지 확인합니다. defaultFactory = MessageResourcesFactory.createFactory()를 통해 리소스 클래스를 생성합니다. ; 존재하는 경우 리소스 클래스를 직접 생성합니다.

initOther() 메소드는 주로 다른 구성을 초기화하고 자체 struts-config 구성 파일의 경로를 얻는 데 사용되며 기본 경로는 web-inf/struts-config.xml입니다. 또한 이 메소드는 Some도 등록합니다. 전환 유형. 구체적인 소스 코드는 다음과 같습니다.


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

initServlet() 메소드는 다이제스터를 사용하여 web.xml 파일을 읽고 이를 servletContext에 넣습니다. 구체적인 구현 소스 코드:


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

먼저 이야기하기 전에, 누구나 쉽게 읽고 이해할 수 있도록 init 메소드의 구체적인 구현 코드를 적어보자.

Init 소스 코드:



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

getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY,this); 이 문장은 ActionServlet 인스턴스가 Globals.ACTION_SERVLET_KEY를 키로 사용하여 servletcontext에 저장된다는 의미입니다.


여기 Globals.ACTION_SERVLET_KEY는 이미 ActionServlet에 다음과 같은 명령문을 제공했습니다.


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完成。

위 내용은 Struts1의 ActionServlet 코드 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.