public void init() throws ServletException {
        final String configPrefix = "config/";
        final int configPrefixLength = configPrefix.length() - 1;

        // Wraps the entire initialization in a try/catch to better handle
        // unexpected exceptions and errors to provide better feedback
        // to the developer
        try {
            initInternal();
            initOther();
            initServlet();
            initChain();
            getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this);
            
            initModuleConfigFactory();

            // 初始化模块配置
            ModuleConfig moduleConfig = initModuleConfig("", config);

            initModuleMessageResources(moduleConfig);
            initModulePlugIns(moduleConfig);
            initModuleFormBeans(moduleConfig);
            initModuleForwards(moduleConfig);
            initModuleExceptionConfigs(moduleConfig);
            initModuleActions(moduleConfig);
            moduleConfig.freeze();

            Enumeration names = getServletConfig().getInitParameterNames();

            while (names.hasMoreElements()) {
                String name = (String) names.nextElement();

                if (!name.startsWith(configPrefix)) {
                    continue;
                }

                String prefix = name.substring(configPrefixLength);

                moduleConfig =
                    initModuleConfig(prefix,
                        getServletConfig().getInitParameter(name));
                initModuleMessageResources(moduleConfig);
                initModulePlugIns(moduleConfig);
                initModuleFormBeans(moduleConfig);
                initModuleForwards(moduleConfig);
                initModuleExceptionConfigs(moduleConfig);
                initModuleActions(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.  Most likely, this is due to an "
                + "incorrect or missing library dependency.", t);
            throw new UnavailableException(t.getMessage());
        }
    }

initModuleConfigFactory方法(初始化模块配置工厂?)

  protected void initModuleConfigFactory() {
        String configFactory =
            getServletConfig().getInitParameter("configFactory");

        if (configFactory != null) {
            //设置class类名,当ModuleConfigFactory调用createFactory时,会拿到当前线程的classloader去加载这个类,并且返回一个实例。
            ModuleConfigFactory.setFactoryClass(configFactory);
        }
    }

初始化模块配置代码

 ModuleConfig moduleConfig = initModuleConfig("", config);
 //config就是struts-config路径,默认/WEB-INF/struts-config.xml

initModuleConfig代码

 protected ModuleConfig initModuleConfig(String prefix, String paths)
        throws ServletException {
        //在这里创建了一个ModuleConfigFactory,如果用户没有配置configFactory,name这个工厂类是org.apache.struts.config.impl.DefaultModuleConfigFactory
        ModuleConfigFactory factoryObject = ModuleConfigFactory.createFactory();
        //创建一个配置,默认是new ModuleConfigImpl(prefix)
        ModuleConfig config = factoryObject.createModuleConfig(prefix);
        //又要解析xml了,其中用到ConfigRuleSet来作为解析规则。也可以自己定义RuleSet来解析
        //如果自定义的话,参数名实rulesets,多个RuleSet类名用逗号分隔
        //自定义ruleset相关代码在initConfigDigester中的addRuleSets中
        Digester digester = initConfigDigester();
        List urls = splitAndResolvePaths(paths);
        URL url;
        for (Iterator i = urls.iterator(); i.hasNext();) {
            url = (URL) i.next();
            digester.push(config);
            //解析每个url,并且处理解析异常。处理解析异常的时候就用到了internal
            this.parseModuleConfigFile(digester, url);
        }
        getServletContext().setAttribute(Globals.MODULE_KEY
            + config.getPrefix(), config);
        return config;
    }

ConfigRuleSet代码

public class ConfigRuleSet extends RuleSetBase {
    public void addRuleInstances(Digester digester) {
        ClassLoader cl = digester.getClassLoader();

        digester.addRule("struts-config/action-mappings",
            new SetActionMappingClassRule());

        digester.addFactoryCreate("struts-config/action-mappings/action",
            new ActionMappingFactory(cl));
        digester.addSetProperties("struts-config/action-mappings/action");
        digester.addSetNext("struts-config/action-mappings/action",
            "addActionConfig", "org.apache.struts.config.ActionConfig");

        digester.addRule("struts-config/action-mappings/action/set-property",
            new BaseConfigSetPropertyRule());

        digester.addObjectCreate("struts-config/action-mappings/action/exception",
            "org.apache.struts.config.ExceptionConfig", "className");
        digester.addSetProperties(
            "struts-config/action-mappings/action/exception");
        digester.addSetNext("struts-config/action-mappings/action/exception",
            "addExceptionConfig", "org.apache.struts.config.ExceptionConfig");

        digester.addRule("struts-config/action-mappings/action/exception/set-property",
            new BaseConfigSetPropertyRule());

        digester.addFactoryCreate("struts-config/action-mappings/action/forward",
            new ActionForwardFactory(cl));
        digester.addSetProperties(
            "struts-config/action-mappings/action/forward");
        digester.addSetNext("struts-config/action-mappings/action/forward",
            "addForwardConfig", "org.apache.struts.config.ForwardConfig");

        digester.addRule("struts-config/action-mappings/action/forward/set-property",
            new BaseConfigSetPropertyRule());

        digester.addObjectCreate("struts-config/controller",
            "org.apache.struts.config.ControllerConfig", "className");
        digester.addSetProperties("struts-config/controller");
        digester.addSetNext("struts-config/controller", "setControllerConfig",
            "org.apache.struts.config.ControllerConfig");

        digester.addRule("struts-config/controller/set-property",
            new BaseConfigSetPropertyRule());

        digester.addRule("struts-config/form-beans",
            new SetActionFormBeanClassRule());

        digester.addFactoryCreate("struts-config/form-beans/form-bean",
            new ActionFormBeanFactory(cl));
        digester.addSetProperties("struts-config/form-beans/form-bean");
        digester.addSetNext("struts-config/form-beans/form-bean",
            "addFormBeanConfig", "org.apache.struts.config.FormBeanConfig");

        digester.addObjectCreate("struts-config/form-beans/form-bean/form-property",
            "org.apache.struts.config.FormPropertyConfig", "className");
        digester.addSetProperties(
            "struts-config/form-beans/form-bean/form-property");
        digester.addSetNext("struts-config/form-beans/form-bean/form-property",
            "addFormPropertyConfig",
            "org.apache.struts.config.FormPropertyConfig");

        digester.addRule("struts-config/form-beans/form-bean/form-property/set-property",
            new BaseConfigSetPropertyRule());

        digester.addRule("struts-config/form-beans/form-bean/set-property",
            new BaseConfigSetPropertyRule());

        digester.addObjectCreate("struts-config/global-exceptions/exception",
            "org.apache.struts.config.ExceptionConfig", "className");
        digester.addSetProperties("struts-config/global-exceptions/exception");
        digester.addSetNext("struts-config/global-exceptions/exception",
            "addExceptionConfig", "org.apache.struts.config.ExceptionConfig");

        digester.addRule("struts-config/global-exceptions/exception/set-property",
            new BaseConfigSetPropertyRule());

        digester.addRule("struts-config/global-forwards",
            new SetActionForwardClassRule());

        digester.addFactoryCreate("struts-config/global-forwards/forward",
            new GlobalForwardFactory(cl));
        digester.addSetProperties("struts-config/global-forwards/forward");
        digester.addSetNext("struts-config/global-forwards/forward",
            "addForwardConfig", "org.apache.struts.config.ForwardConfig");

        digester.addRule("struts-config/global-forwards/forward/set-property",
            new BaseConfigSetPropertyRule());

        digester.addObjectCreate("struts-config/message-resources",
            "org.apache.struts.config.MessageResourcesConfig", "className");
        digester.addSetProperties("struts-config/message-resources");
        digester.addSetNext("struts-config/message-resources",
            "addMessageResourcesConfig",
            "org.apache.struts.config.MessageResourcesConfig");

        digester.addRule("struts-config/message-resources/set-property",
            new BaseConfigSetPropertyRule());

        digester.addObjectCreate("struts-config/plug-in",
            "org.apache.struts.config.PlugInConfig");
        digester.addSetProperties("struts-config/plug-in");
        digester.addSetNext("struts-config/plug-in", "addPlugInConfig",
            "org.apache.struts.config.PlugInConfig");

        digester.addRule("struts-config/plug-in/set-property",
            new PlugInSetPropertyRule());

        // PluginConfig does not extend BaseConfig, at least for now.
    }
}
final class PlugInSetPropertyRule extends Rule {
    public PlugInSetPropertyRule() {
        super();
    }

    public void begin(String namespace, String names, Attributes attributes)
        throws Exception {
        PlugInConfig plugInConfig = (PlugInConfig) digester.peek();
        plugInConfig.addProperty(attributes.getValue("property"),
            attributes.getValue("value"));
    }
}
final class SetActionFormBeanClassRule extends Rule {
    public SetActionFormBeanClassRule() {
        super();
    }
    public void begin(String namespace, String name, Attributes attributes)
        throws Exception {
        String className = attributes.getValue("type");

        if (className != null) {
            ModuleConfig mc = (ModuleConfig) digester.peek();

            mc.setActionFormBeanClass(className);
        }
    }
}
final class BaseConfigSetPropertyRule extends SetPropertyRule {
    public BaseConfigSetPropertyRule() {
        super("property", "value");
    }

    public void begin(Attributes attributes)
        throws Exception {
        if (attributes.getIndex("key") == -1) {
            super.begin(attributes);

            return;
        }

        if (attributes.getIndex("property") != -1) {
            throw new IllegalArgumentException(
                "<set-property> accepts only one of 'key' or 'property' attributes.");
        }

        Object topOfStack = digester.peek();

        if (topOfStack instanceof BaseConfig) {
            BaseConfig config = (BaseConfig) topOfStack;

            config.setProperty(attributes.getValue("key"),
                attributes.getValue("value"));
        } else {
            throw new IllegalArgumentException(
                "'key' attribute of <set-property> only applicable to subclasses of BaseConfig; "
                + "object on top of stack is " + topOfStack + " [key: "
                + attributes.getValue("key") + ", value: "
                + attributes.getValue("value") + "]");
        }
    }
}
final class ActionFormBeanFactory extends AbstractObjectCreationFactory {
    private ClassLoader cl;

    public ActionFormBeanFactory(ClassLoader cl) {
        super();
        this.cl = cl;
    }
    public Object createObject(Attributes attributes) {
        // Identify the name of the class to instantiate
        String className = attributes.getValue("className");
        if (className == null) {
            ModuleConfig mc = (ModuleConfig) digester.peek();

            className = mc.getActionFormBeanClass();
        }
        // Instantiate the new object and return it
        Object actionFormBean = null;

        try {
            actionFormBean = RequestUtils.applicationInstance(className, cl);
        } catch (Exception e) {
            digester.getLogger().error("ActionFormBeanFactory.createObject: ", e);
        }
        return actionFormBean;
    }
}
final class SetActionMappingClassRule extends Rule {
    public SetActionMappingClassRule() {
        super();
    }

    public void begin(String namespace, String name, Attributes attributes)
        throws Exception {
        String className = attributes.getValue("type");

        if (className != null) {
            ModuleConfig mc = (ModuleConfig) digester.peek();

            mc.setActionMappingClass(className);
        }
    }
}
final class ActionMappingFactory extends AbstractObjectCreationFactory {
    private ClassLoader cl;

    public ActionMappingFactory(ClassLoader cl) {
        super();
        this.cl = cl;
    }

    public Object createObject(Attributes attributes) {
        // Identify the name of the class to instantiate
        String className = attributes.getValue("className");

        if (className == null) {
            ModuleConfig mc = (ModuleConfig) digester.peek();

            className = mc.getActionMappingClass();
        }

        // Instantiate the new object and return it
        Object actionMapping = null;

        try {
            actionMapping = RequestUtils.applicationInstance(className, cl);
        } catch (Exception e) {
            digester.getLogger().error("ActionMappingFactory.createObject: ", e);
        }

        return actionMapping;
    }
}
final class SetActionForwardClassRule extends Rule {
    public SetActionForwardClassRule() {
        super();
    }

    public void begin(String namespace, String name, Attributes attributes)
        throws Exception {
        String className = attributes.getValue("type");

        if (className != null) {
            ModuleConfig mc = (ModuleConfig) digester.peek();

            mc.setActionForwardClass(className);
        }
    }
}
final class GlobalForwardFactory extends AbstractObjectCreationFactory {
    private ClassLoader cl;

    public GlobalForwardFactory(ClassLoader cl) {
        super();
        this.cl = cl;
    }

    public Object createObject(Attributes attributes) {
        // Identify the name of the class to instantiate
        String className = attributes.getValue("className");

        if (className == null) {
            ModuleConfig mc = (ModuleConfig) digester.peek();

            className = mc.getActionForwardClass();
        }

        // Instantiate the new object and return it
        Object globalForward = null;

        try {
            globalForward = RequestUtils.applicationInstance(className, cl);
        } catch (Exception e) {
            digester.getLogger().error("GlobalForwardFactory.createObject: ", e);
        }

        return globalForward;
    }
}
final class ActionForwardFactory extends AbstractObjectCreationFactory {
    private ClassLoader cl;

    public ActionForwardFactory(ClassLoader cl) {
        super();
        this.cl = cl;
    }

    public Object createObject(Attributes attributes) {
        // Identify the name of the class to instantiate
        String className = attributes.getValue("className");

        if (className == null) {
            ModuleConfig mc = (ModuleConfig) digester.peek(1);

            className = mc.getActionForwardClass();
        }

        // Instantiate the new object and return it
        Object actionForward = null;

        try {
            actionForward = RequestUtils.applicationInstance(className, cl);
        } catch (Exception e) {
            digester.getLogger().error("ActionForwardFactory.createObject: ", e);
        }
        return actionForward;
    }
}