`
dowhathowtodo
  • 浏览: 780686 次
文章分类
社区版块
存档分类
最新评论

深入浅出学习Struts框架(七):ActionServlet实例化之读取struts-config.xml配置文件

 
阅读更多

在上一篇博客中讲到ActionServlet是如何初始化的以及web.xml的配置信息的具体作用。今天我们讲继续讲解ActionServlet在初始化的时候如何读取/WEB-INF/struts-config.xml信息到内存中,如何将这些从配置文件读取的信息以Actionmapping的形式展现在内存中的。

由于这部分内容是比较繁琐的,所以我对这部分的深入分析也不能太详细,但是具体实现流程我会讲清晰,如果有兴趣研究的童鞋们希望能够继续深入,研究的非常透彻的时候,可以给我发邮件或Q我。

下面来开始今天的博客,我们先从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)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) {
 
            // The follow error message is not retrieved from internal message
            // resources as they may not have been able to have been
            // initialized
            log.error("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 = MessageResources.getMessageResources(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 1.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()) {
            log.debug("Mapping for servlet '" + servletName + "' = '" +
                servletMapping + "'");
        }

        if (servletMapping != null) {
            getServletContext().setAttribute(Globals.SERVLET_KEY, servletMapping);
        }

    }


这篇博客先介绍这几个方法,随着这些方法具体作用和具体实现的慢慢的我们就知道init方法的作用,也慢慢的就解开了当我们实例化ActionServlet的时候,digester是如何读取/WEB-INF/struts-config.xml的文件内容,并且放到了ActionMapping中。敬请期待!

分享到:
评论

相关推荐

    外文翻译 stus MVC

    The file struts-config.xml instructs ActionServlet on how to use the extended classes. There are several advantages to this approach: • The entire logical flow of the application is in a ...

    ssh(structs,spring,hibernate)框架中的上传下载

    WEB-INF下的applicationContext.xml为Spring的配置文件,struts-config.xml为Struts的配置文件,file-upload.jsp为文件上传页面,file-list.jsp为文件列表页面。  本文后面的章节将从数据持久层->业务层->Web层的...

    Spring面试题

    ActionServler根据Struts-config.xml文件配置好的设置决定是否需要表单验证,如果需要就调用ActionForm的 Validate()验证后选择将请求发送到哪个Action,如果Action不存在,ActionServlet会先创建这个对象,然后...

    Java Web编程宝典-十年典藏版.pdf.part2(共2个)

    第1篇为技能学习篇,主要包括Java Web开发环境、JSP语法、JSP内置对象、Java Bean技术、Servlet技术、EL与JSTL标签库、数据库应用开发、初识Struts2基础、揭密Struts2高级技术、Hib锄劬e技术入门、Hibernate高级应用...

    java面试题

    答:Struts1和Struts2是两个完全不同的框架,Struts1以ActionServlet作为核心控制器,由ActionServlet负责拦截用户的所有请求。Struts2以核心控制器FilterDispatcher为基础,包含了框架内部的控制流程和处理机制。 ...

    MLDN+李兴华+Java+Web开发实战经典.part3.rar )

    17.5、Action深入 17.5.1、ForwardAction 17.5.2、IncludeAction 17.5.3、DispatchAction 17.6、验证框架 附录A:实用工具 18.1、JavaMail 18.1.1、James邮件服务器的下载及配置 18.1.2、JavaMail...

    java web 视频、电子书、源码(李兴华老师出版)

    17.5、Action深入 17.5.1、ForwardAction 17.5.2、IncludeAction 17.5.3、DispatchAction 17.6、验证框架 附录A:实用工具 18.1、JavaMail 18.1.1、James邮件服务器的下载及配置 18.1.2、JavaMail...

    李兴华Java Web开发实战经典.pdf (高清版) Part1

    17.5、Action深入 17.5.1、ForwardAction 17.5.2、IncludeAction 17.5.3、DispatchAction 17.6、验证框架 附录A:实用工具 18.1、JavaMail 18.1.1、James邮件服务器的下载及配置 18.1.2、JavaMail...

    李兴华 Java Web 开发实战经典_带源码_高清pdf 带书签 上

    17.5、Action深入 17.5.1、ForwardAction 17.5.2、IncludeAction 17.5.3、DispatchAction 17.6、验证框架 附录A:实用工具 18.1、JavaMail 18.1.1、James邮件服务器的下载及配置 18.1.2、JavaMail简介及配置...

    李兴华 java_web开发实战经典 源码 完整版收集共享

    17.5、Action深入 17.5.1、ForwardAction 17.5.2、IncludeAction 17.5.3、DispatchAction 17.6、验证框架 附录A:实用工具 18.1、JavaMail 18.1.1、James邮件服务器的下载及配置 18.1.2、JavaMail简介及配置...

    李兴华 Java Web 开发实战经典_带源码_高清pdf 带书签 下

    17.5、Action深入 17.5.1、ForwardAction 17.5.2、IncludeAction 17.5.3、DispatchAction 17.6、验证框架 附录A:实用工具 18.1、JavaMail 18.1.1、James邮件服务器的下载及配置 18.1.2、JavaMail简介及配置...

    李兴华 Java Web 开发实战经典 高清扫描版Part3

    17.5、Action深入 17.5.1、ForwardAction 17.5.2、IncludeAction 17.5.3、DispatchAction 17.6、验证框架 附录A:实用工具 18.1、JavaMail 18.1.1、James邮件服务器的下载及配置 18.1.2、JavaMail简介及配置...

    李兴华Java Web开发实战经典(高清版) Part2

    17.5、Action深入 17.5.1、ForwardAction 17.5.2、IncludeAction 17.5.3、DispatchAction 17.6、验证框架 附录A:实用工具 18.1、JavaMail 18.1.1、James邮件服务器的下载及配置 18.1.2、JavaMail...

    java 面试题 总结

    Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,当服务器决定将实例销毁的时候调用其destroy方法。 与cgi的区别...

    超级有影响力霸气的Java面试题大全文档

     Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,当服务器决定将实例销毁的时候调用其destroy方法。 与cgi的区别...

Global site tag (gtag.js) - Google Analytics