CenturyMagus的专栏

www.err123.cn ,收集各类编程错误的解决方案,欢迎大家访问

用户操作
[即时聊天] [发私信] [加为好友]
magusID:CenturyMagus
62785次访问,排名1686好友2人,关注者3
CenturyMagus的文章
原创 42 篇
翻译 1 篇
转载 40 篇
评论 23 篇
CenturyMagus的公告

ah011一起在友播听歌吧!
最近评论
zhengyuanting:通过URL传中文,如果不是post的话,是会乱码的
qq386232894:好文章!!!!
fz04003:谢谢啊,我终于搞懂这个东西了。
虽然我用的是JQuery,但是终于搞懂Struts这块是怎么回事了,谢谢!
小脚:终于全部搞懂了!!!谢谢老大~
小小鸟:好文章.比其他好多地方都讲的清楚透彻.赞一个.
文章分类
收藏
    相册
    编程网站
    Apache
    IBM DeveloperWorks
    onjava
    W3C
    编程错误解决方案收集
    计算机词汇在线词典
    存档
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    转载 Struts 源码学习之ActionServlet ( 一)收藏

    新一篇: Struts源码学习之ActionServlet(二) | 旧一篇: Linux下的压缩文件剖析

    转载自 http://www.blogjava.net/xiaodaoxiaodao/archive/2007/04/26/113666.html 

     

     

    Struts 源码学习之ActionServlet ( )

     

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

    // convertNull trueJava包装类(如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 String internalName = "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 String factoryClass =

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

    如果这个参数的值为 true true/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 void addServletMapping(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);

    }

     

    发表于 @ 2008年07月22日 09:25:00|评论(loading...)|编辑|收藏

    新一篇: Struts源码学习之ActionServlet(二) | 旧一篇: Linux下的压缩文件剖析

    评论:没有评论。

    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © CenturyMagus