Struts 源码学习之ActionServlet ( 一)

来源:互联网 发布:mysql qps 和 tps 编辑:程序博客网 时间:2024/05/17 01:08

Struts源码最新版本为 struts-1.3.8-src.zip 12-Mar-2007 00:06

学习笔记使用struts-1.3.5-src.zip的源码,

下载地址:http://archive.apache.org/dist/struts/source/

1. web.xml中通过下面定义把所有的*.do交给ActionServlet处理

 

<!-- Standard Action Servlet Configuration (with debugging) -->

<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,

         /WEB-INF/struts-config-Wildcard.xml

      </param-value>

   </init-param>

   <load-on-startup>2</load-on-startup>

 </servlet>

 

 <!-- Standard Action Servlet Mapping -->

 <servlet-mapping>

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

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

 </servlet-mapping>

 

2. 下面研究一下struts的源码,由于servlet设置了load-on-startup,所以tomcat启动时会加载ActionServlet,也就是会执行ActionServlet中的init()方法,Struts的初始化实现就是在这里实现的

 

注:由于servlet的生命周期为 web容器加载和实例化类/init()初始化/service()请求处理/destroy()四个阶段,而init()方法在tomcat启动后只执行一次,所以如果想在tomcat启动后用debug模式查看ActionServletinit()方法的执行,可以把上面的<load-on-startup>2</load-on-startup>注释掉就可以了(不过真正开发时还是需要的)。

 

3. ActionServlet中定义了一些常量,如下:

   // 默认的struts配置文件为/WEB-INF/struts-config.xml

   protected String config = "/WEB-INF/struts-config.xml"; // initOther(); initModuleConfig ();

 

   // 默认的链(定义了一个按顺序执行的处理流程)配置文件

protected String chainConfig = "org/apache/struts/chain/chain-config.xml";

// initChain();

 

protected Digester configDigester = null; // initModuleConfig ();

// convertNulltrueJava包装类(如java.lang.Integer)的初始值为null

protected boolean convertNull = false; // initOther();

 

protected MessageResources internal = null; // initInternal();

// 默认的struts-core-1.3.5.jar 中资源文件为ActionResources.properties

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

// initInternal();

 

// 一些文档类型定义,用来验证相应的配置文件如struts-config.xml是否正确

   protected String[] registrations =

       {

           "-//Apache Software Foundation//DTD Struts Configuration 1.0//EN",

           "/org/apache/struts/resources/struts-config_1_0.dtd",

           "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN",

           "/org/apache/struts/resources/struts-config_1_1.dtd",

           "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN",

           "/org/apache/struts/resources/struts-config_1_2.dtd",

           "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN",

           "/org/apache/struts/resources/struts-config_1_3.dtd",

           "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN",

           "/org/apache/struts/resources/web-app_2_3.dtd"

       }; // initServlet();

   protected String servletMapping = null; // initServlet();

protected String servletName = null; // initServlet();

 

4. ActionServlet中的init()方法执行流程如下

 

struts_src.jpg 

① 内部资源文件ActionResources.properties的初始化 initInternal();

protected MessageResources internal = null; // initInternal();

protected StringinternalName = "org.apache.struts.action.ActionResources"; // initInternal();

 

// initInternal方法中通过下面得到一个MessageResources对象

internal = MessageResources.getMessageResources(internalName);

此资源文件主要包括一些消息信息的定义,具体可参考org.apache.struts.action下的ActionResources.properties文件

 

MessageResources.java中的getMessageResources方法,

       if (defaultFactory == null) {

           defaultFactory = MessageResourcesFactory.createFactory();//

       }

       return defaultFactory.createResources(config); //传入internalName//

 

MessageResourcesFactory.createFactory()所做的工作:

protected static transient Class clazz = null;

protected static StringfactoryClass =

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

clazz =RequestUtils.applicationClass(factoryClass);

RequestUtils.applicationClass通过classLoader加载一个

org.apache.struts.util.PropertyMessageResourcesFactory

 

defaultFactory.createResources(config)所做的工作:

this.factory = factory;

("org.apache.struts.util.PropertyMessageResourcesFactory")

this.config = config;("org.apache.struts.action.ActionResources")

this.returnNull = returnNull;(true)

PropertyMessageResourcesFactory extends MessageResourcesFactory

返回一个MessageResources对象

 

 

② 调用initOther(); web.xml中加载ActionServlet的初始化参数,包括config/convertNull

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

protected boolean convertNull = false; // initOther();

 

//得到web.xml"config"参数

String value;

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

if (value != null) {

   config = value;

}

   <servlet>

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

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

       <init-param>

           <param-name>config</param-name>   <!--得到"config"参数-->

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

       </init-param>

       <init-param>

           <param-name>convertNull</param-name>   <!--得到"convertNull"参数-->

           <param-value>true</param-value>

       </init-param>

       .......

   </servlet>   

 

//获得convertNull的值(true/yes/on/y/1

getServletConfig().getInitParameter("convertNull");

如果这个参数的值为 truetrue/yes/on/y/1, 数值型(BigDecimal/BigInteger/Boolean/Byte/Character/Double/Float/Integer/Long/Short)Java包装类(比如java.lang.Integer)的初始值为null,而非0。缺省值[false]

 

使其初始值为null的方法如下:

//将所有的转换器注销掉

ConvertUtils.deregister();

//为指定类型clazz注册转换器converter

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

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

.......

 

注:ConvertUtils 用法如下

deregister() deregister (java.lang.Class clazz)

注销转换器,前者将所有的转换器注销掉,后者只注销对应于clazz的转换器register(Converter  converter, java.lang.Class clazz)

为指定类型clazz注册转换器converter。如果clazz已经存在一个对应的转换器,那么converter覆盖原来的转换器。

 

 

③ 调用initServlet(); web.xml中加载ActionServlet的初始化参数如servlet-name,加载DTD文件并把其放入HashMap缓存,读取并解析web.xml的内容

// Remember our servlet name

getServletConfig().getServletName();

<servlet>

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

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

       <init-param>

           <param-name>config</param-name>   <!--得到"config"参数-->

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

       </init-param>

       <init-param>

           <param-name>convertNull</param-name>   <!--得到"convertNull"参数-->

           <param-value>true</param-value>

       </init-param>

       .......

   </servlet>

 

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

Digester digester = new Digester();

//把当前的 ActionServlet对象放入到解析堆栈中

digester.push(this);

//指明要考虑命名空间

digester.setNamespaceAware(true);

//缺省值[false],解析器只是检查XML是否格式良好(well formed)

digester.setValidating(false);

 

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

//struts 可使用 struts-core-1.3.5.jar 中的DTD中来处理struts配置文件,这样可适用于那些没有连接到internet的应用环境

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

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

 

           if (url != null) {

               // 读取DTD文件并把其放入HashMap缓存

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

           }

       }

 

/************************************************************

// 一些文档类型定义,用来验证相应的配置文件如struts-config.xml是否正确

   protected String[] registrations =

       {

           "-//Apache Software Foundation//DTD Struts Configuration 1.0//EN",

           "/org/apache/struts/resources/struts-config_1_0.dtd",

           "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN",

           "/org/apache/struts/resources/struts-config_1_1.dtd",

           "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN",

           "/org/apache/struts/resources/struts-config_1_2.dtd",

           "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN",

           "/org/apache/struts/resources/struts-config_1_3.dtd",

           "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN",

           "/org/apache/struts/resources/web-app_2_3.dtd"

       }; // initServlet();

************************************************************/

 

// Configure the processing rules that we need

//运行时,digester 就会调用 ActionServlet中的 addServletMapping()方法,并传入两个参数

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);

得到

<servlet-mapping>

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

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

</servlet-mapping>

 

/************************************************************

//来判断当前 servlet 名称是否为正在运行的 servlet 名称,如是,就把 url-pattern 作为 servletMapping

public voidaddServletMapping(String servletName, String urlPattern) {

       if (servletName == null) {

           return;

       }

       if (servletName.equals(this.servletName)) {

           if (log.isDebugEnabled()) {

               log.debug("Process servletName=" + servletName

                   + ", urlPattern=" + urlPattern);

           }

           this.servletMapping = urlPattern;

       }

}

************************************************************/

 

//读取配置文件web.xml的内容

InputStream input = getServletContext().getResourceAsStream("/WEB-INF/web.xml");

//如找不到/WEB-INF/web.xml文件,则报错

if (input == null) {

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

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

}

/************************************************************

//报错信息定义在org\apache\struts\action\ActionResources.properties

configWebXml=The /WEB-INF/web.xml was not found.

************************************************************/

 

//解析input流文件,每读到一个节点元素就触发一个事件

digester.parse(input);

 

注:Digester 是一个基于 DOM SAX 实现的类,它是事件触发的,可以将XML文件转换为任意的Java对象,支持规则的对任意XML文档的处理。原先是struts项目的一部分,后因其通用性而划归Commons子项目。

 

//servletMapping存储到servletContext中,属性名为Globals.SERVLET_KEY " org.apache.struts.action.SERVLET_MAPPING"

if (servletMapping != null) {

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

}

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 吃酸的牙齿酸软怎么办 吃酸东西牙齿酸怎么办 拔完智齿神经疼怎么办 22岁腿关节疼痛怎么办 耳洞里面有硬块怎么办 耳洞发炎有硬块怎么办 小孩慢性扁桃体发炎怎么办大全 侧切伤口化脓了怎么办 狗狗伤口不愈合怎么办 狗后腿烂了化脓怎么办 乳腺增生腋下淋巴结肿大怎么办 手术刀口冒脓了怎么办 脚伤口感染肿了怎么办 皮外伤口不愈合怎么办 烫伤新皮红红的怎么办 脸上痘痘化脓了怎么办 痘痘引起的红肿怎么办 痘痘引起的硬块怎么办 痘痘化脓感染了怎么办 烫伤有脓了烂掉怎么办 烫伤起泡破皮了怎么办 一出汗就有狐臭怎么办 耳朵后面臭臭的怎么办 赤黑abo意外怀孕怎么办 qq忘记密保了怎么办 三星s8耗电太快怎么办 360云盘关闭照片怎么办 360云盘停止服务怎么办 房间湿度90%太高怎么办 天刀掠夺进错了怎么办 狗耳朵臭怎么办黄垢 狗耳朵里有味道怎么办 电视没了泰捷怎么办 配资公司跑路怎么办 口袋忍者倒闭了怎么办 小樱死了,佐助怎么办 别人诬陷我我该怎么办 亲戚诬陷我偷钱怎么办 被别人怀疑偷钱怎么办 有人诬陷我偷鱼怎么办, 寝室里有人偷钱怎么办