全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

struts1之ActionServlet详解_动力节点Java学院整理

在web.xml中我们除了配置ActionServlet还配置了一些初始化参数信息,首先我们看第一个config参数,这里配置的是/WEB-INF/struts-config.xml,因为要下面传递一个这样一个配置信息,这个xml文件名是struts1标准的名字,所以这里这个初始化信息完全可以删除,如果不用这个标准名称这里就必须要在这里配置。现在我们配置的是标准名字,所以我们可以删除,这是为什么呢?这里要看ActionServlet源代码才可以。

从图片上我们能看到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方法的源代码如下:

/** 
   * <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()方法。这个方法的实现代码是:

代码段一:

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

代码段二:

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

代码段三:

/** 
   * 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,另外这个方法还会注册一些转换类的。具体源代码是:

/** 
   * <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中。具体实现源代码:

/** 
 * <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源代码:

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已经给出了声明:

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


# struts1  # ActionServlet  # struts  # Java框架Struts2实现图片上传功能  # Java框架学习Struts2复选框实例代码  # struts2标签总结_动力节点Java学院整理  # struts1之简单mvc示例_动力节点Java学院整理  # Struts1之url截取_动力节点Java学院整理  # Struts1教程之ActionMapping_动力节点Java学院整理  # java struts2框架简介  # Java struts2 package元素配置及实例解析  # 配置文件  # 源代码  # 的是  # 这段  # 就会  # 就不  # 这两个  # 要看  # 有必要  # 当我们  # 自己的  # 这是  # 几个  # 也不  # 很好  # 好了  # 出了  # 第一个  # 尤其是  # 一句 


相关文章: 在线ppt制作网站有哪些软件,如何把网页的内容做成ppt?  制作国外网站的软件,国外有哪些比较优质的网站推荐?  建站之星2.7模板:企业网站建设与h5定制设计专题  如何在景安服务器上快速搭建个人网站?  制作网站公司那家好,网络公司是做什么的?  如何处理“XML格式不正确”错误 常见XML well-formed问题解决方法  名字制作网站免费,所有小说网站的名字?  建站主机与虚拟主机有何区别?如何选择最优方案?  网站制作服务平台,有什么网站可以发布本地服务信息?  昆明网站制作哪家好,昆明公租房申请网上登录入口?  西安专业网站制作公司有哪些,陕西省建行官方网站?  如何用西部建站助手快速创建专业网站?  如何高效生成建站之星成品网站源码?  实现点击下箭头变上箭头来回切换的两种方法【推荐】  网站专业制作公司,网站编辑是做什么的?好做吗?工作前景如何?  GML (Geography Markup Language)是什么,它如何用XML来表示地理空间信息?  如何在IIS中配置站点IP、端口及主机头?  如何在云主机上快速搭建网站?  公司门户网站制作流程,华为官网怎么做?  如何用已有域名快速搭建网站?  济南企业网站制作公司,济南社保单位网上缴费步骤?  清单制作人网站有哪些,近日“兴风作浪的姑奶奶”引起很多人的关注这是什么事情?  免费视频制作网站,更新又快又好的免费电影网站?  视频网站制作教程,怎么样制作优酷网的小视频?  相亲简历制作网站推荐大全,新相亲大会主持人小萍萍资料?  SQL查询语句优化的实用方法总结  如何通过FTP空间快速搭建安全高效网站?  购物网站制作公司有哪些,哪个购物网站比较好?  Android自定义listview布局实现上拉加载下拉刷新功能  如何基于云服务器快速搭建网站及云盘系统?  青岛网站建设如何选择本地服务器?  开源网站制作软件,开源网站什么意思?  杭州银行网站设计制作流程,杭州银行怎么开通认证方式?  TestNG的testng.xml配置文件怎么写  如何快速搭建高效香港服务器网站?  如何在腾讯云免费申请建站?  宁波自助建站系统如何快速打造专业企业网站?  制作门户网站的参考文献在哪,小说网站怎么建立?  大连企业网站制作公司,大连2025企业社保缴费网上缴费流程?  香港代理服务器配置指南:高匿IP选择、跨境加速与SEO优化技巧  内网网站制作软件,内网的网站如何发布到外网?  建站之星如何实现五合一智能建站与营销推广?  如何在Golang中指定模块版本_使用go.mod控制版本号  建站主机服务器选型指南与性能优化方案解析  如何解决ASP生成WAP建站中文乱码问题?  如何在阿里云ECS服务器部署织梦CMS网站?  专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?  如何在Ubuntu系统下快速搭建WordPress个人网站?  如何有效防御Web建站篡改攻击?  建站之星与建站宝盒如何选择最佳方案? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。