`

Struts2源码浅析-初始化

 
阅读更多
StrutsPrepareAndExecuteFilter实现了Filter接口  init方法为初始化入口
StrutsPrepareAndExecuteFilter init方法
public void init(FilterConfig filterConfig) throws ServletException {  
    //初始化辅助类 类似一个Delegate  
     InitOperations init = new InitOperations();  
     try {  
        // FilterHostConfig 封装了FilterConfig参数对象   
         FilterHostConfig config = new FilterHostConfig(filterConfig);  
         //LoggerFactory配置加载   
         //如果没有web.xml 没有配置“loggerFactory”参数  尝试org.apache.commons.logging.LogFactory  
         //如果失败 使用JdkLoggerFactory  
         //TODO SPI  
         init.initLogging(config);  
         //TODO 创建Dispatcher 注册加载器   执行加载器  创建容器 解析xml    
         Dispatcher dispatcher = init.initDispatcher(config);  
         init.initStaticContentLoader(config, dispatcher);  
         //预处理类 请求处理时才会真正用到  
         //1.主要负责在每次请求 创建ActionContext 清除ActionContext  
         //2.当接收到一个请求时 通过uri查找 ActionConfig 创建ActionMapping  
         prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);  
         //处理请求  Delegate  
         execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);  
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);  
//空实现 留作扩展  
         postInit(dispatcher, filterConfig);  
     } finally {  
         init.cleanup();  
     }  
 }  

InitOperations 类似与一个Delegate 主要负责实例化Dispatche  再把初始化操作转交给Dispatche init处理

public Dispatcher initDispatcher( HostConfig filterConfig ) {  
    //创建Dispatcher  
    Dispatcher dispatcher = createDispatcher(filterConfig);  
    //核心方法  Container容器的创建   xml解析在此方法发生  
    dispatcher.init();  
    return dispatcher;  
}  
  
private Dispatcher createDispatcher( HostConfig filterConfig ) {  
    Map<String, String> params = new HashMap<String, String>();  
    for ( Iterator e = filterConfig.getInitParameterNames(); e.hasNext(); ) {  
        String name = (String) e.next();  
        String value = filterConfig.getInitParameter(name);  
        params.put(name, value);  
    }  
    return new Dispatcher(filterConfig.getServletContext(), params);  
}  

Dispatcher init方法  1.针对配置文件 注册不同的加载器 保存到ConfigurationManager类中的一个变量中  2.创建容器 解析xml

public void init() {  
    //创建配置操作管理类  ,  会保存元素加载器   
    if (configurationManager == null) {  
        configurationManager = createConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);  
    }  
       try {  
        /**初始化各种形式加载器,保存到ConfigurationManager#containerProviders Map集合中 没有真正执行加载 解析逻辑*/  
          
        //org/apache/struts2/default.properties属性文件  里面定义了一系列struts常量  
           init_DefaultProperties(); // [1]  
             
           //web.xml配置的 config参数 [配置多个用","分开]  
           //如果没有该参数 默认为 struts-default.xml[框架级],struts-plugin.xml[框架级],struts.xml[系统级别]  
           //根据文件名称 创建加载器  加载xml主要有一下两个解析器  
           //XmlConfigurationProvider[xwork.xml],  
           //StrutsXmlConfigurationProvider[struts相关配置文件]配置元素加载器   
           init_TraditionalXmlConfigurations(); // [2]  
             
           //struts.locale 注册  
           init_LegacyStrutsProperties(); // [3]  
             
           //实例化  我们自定义的加载器  保存到containerProviders集合中  
           // web.xml configProviders参数  多个用","分开  配置器必须是ConfigurationProvider接口的实例  
           //TODO SPI  
           init_CustomConfigurationProviders(); // [5]  
             
           //web.xml配置的init-param参数 加载器  最终会保存到Container容器中  
           init_FilterInitParameters() ; // [6]  
             
           //TODO 根据我们在struts.xml定义的 常量 选择插件类     
           //比如集成spring 会用到org.apache.struts2.spring.StrutsSpringObjectFactory   
           init_AliasStandardObjects() ; // [7]  
             
           /** 执行加载器 */  
           //TODO 创建容器  解析xml  真正执行加载器方法   
           Container container = init_PreloadConfiguration();  
           //执行当前Dispatcher对象 依赖关系注入   
           container.inject(this);  
             
           //额外动作   
           init_CheckConfigurationReloading(container);  
           init_CheckWebLogicWorkaround(container);  
  
       } catch (Exception ex) {  
           if (LOG.isErrorEnabled())  
               LOG.error("Dispatcher initialization failed", ex);  
           throw new StrutsException(ex);  
       }  
   }  

ConfigurationManager 主要管理 创建的各种加载器

public class ConfigurationManager {  
  
    protected static final Logger LOG = LoggerFactory.getLogger(ConfigurationManager.class);  
    //配置元素管理器  
    protected Configuration configuration;  
      
    protected Lock providerLock = new ReentrantLock();  
    //创建的xml加载器会保存到次集合中  
    private List<ContainerProvider> containerProviders = new CopyOnWriteArrayList<ContainerProvider>();  
      
} 

Dispatcher的 createConfigurationManager方法

protected ConfigurationManager createConfigurationManager(String name) {  
    //name - >  struts  
    return new ConfigurationManager(name);  
}  

1.default.properties 属性文件加载器

private void init_DefaultProperties() {  
    //保存到ConfigurationManager加载器集合中  
    configurationManager.addConfigurationProvider(new DefaultPropertiesProvider());  
}  

2.创建struts相关文件加载器 StrutsXmlConfigurationProvider

private void init_TraditionalXmlConfigurations() {  
    //web.xml 配置的config  
    String configPaths = initParams.get("config");  
    if (configPaths == null) {  
        //如果没有配置  默认 struts-default.xml,struts-plugin.xml,struts.xml  
        configPaths = DEFAULT_CONFIGURATION_PATHS;  
    }  
    String[] files = configPaths.split("\\s*[,]\\s*");  
    for (String file : files) {  
        if (file.endsWith(".xml")) {  
            if ("xwork.xml".equals(file)) {  
                configurationManager.addConfigurationProvider(createXmlConfigurationProvider(file, false));  
            } else {  
                //struts xml加载器    
                //StrutsXmlConfigurationProvider  
                configurationManager.addConfigurationProvider(createStrutsXmlConfigurationProvider(file, false, servletContext));  
            }  
        } else {  
            throw new IllegalArgumentException("Invalid configuration file name");  
        }  
    }  
}  
  
protected XmlConfigurationProvider createXmlConfigurationProvider(String filename, boolean errorIfMissing) {  
    return new XmlConfigurationProvider(filename, errorIfMissing);  
}  
  
protected XmlConfigurationProvider createStrutsXmlConfigurationProvider(String filename, boolean errorIfMissing, ServletContext ctx) {  
    return new StrutsXmlConfigurationProvider(filename, errorIfMissing, ctx);  
}  

3.web.xml扩展的ContainerProviders加载器 实例化

private void init_CustomConfigurationProviders() {  
    //web.xml 中configProviders 节点  
    String configProvs = initParams.get("configProviders");  
    if (configProvs != null) {  
        String[] classes = configProvs.split("\\s*[,]\\s*");  
        for (String cname : classes) {  
         Class cls = ClassLoaderUtils.loadClass(cname, this.getClass());  
         ConfigurationProvider prov = (ConfigurationProvider)cls.newInstance();  
         configurationManager.addConfigurationProvider(prov);  
        }  
    }  
}  

init_PreloadConfiguration 方法主要完成创建容器, 解析xml动作

private Container init_PreloadConfiguration() {  
    //创建Container  解析xml  
    Configuration config = configurationManager.getConfiguration();  
    Container container = config.getContainer();  
  
    boolean reloadi18n = Boolean.valueOf(container.getInstance(String.class, StrutsConstants.STRUTS_I18N_RELOAD));  
    LocalizedTextUtil.setReloadBundles(reloadi18n);  
    return container;  
}  

init_PreloadConfiguration 方法中调用了  ConfigurationManager的getConfiguration 方法

public synchronized Configuration getConfiguration() {  
    //创建配置元素管理器  
    if (configuration == null) {  
        // defaultFrameworkBeanName  - > struts  
        setConfiguration(createConfiguration(defaultFrameworkBeanName));  
        try {  
            // getContainerProviders  返回注册的各种加载器   
            // reloadContainer  创建Container  解析xml  
            configuration.reloadContainer(getContainerProviders());  
        } catch (ConfigurationException e) {  
            setConfiguration(null);  
            throw new ConfigurationException("Unable to load configuration.", e);  
        }  
    } else {  
        conditionalReload();  
    }  
    return configuration;  
}  


protected Configuration createConfiguration(String beanName) {  
    return new DefaultConfiguration(beanName);  
}  

DefaultConfiguration的reloadContainer方法 会去执行已注册的各种加载器 ,和创建容器

public synchronized List<PackageProvider> reloadContainer(List<ContainerProvider> providers) throws ConfigurationException {  
        packageContexts.clear();  
        loadedFileNames.clear();  
        List<PackageProvider> packageProviders = new ArrayList<PackageProvider>();  
        // 保存struts常量  
        ContainerProperties props = new ContainerProperties();  
        //容器构建器  
        ContainerBuilder builder = new ContainerBuilder();  
        for (final ContainerProvider containerProvider : providers) {  
            /** 
             * 初始化Document 准备解析 
             * 具体在XmlConfigurationProvider实现类 会处理include节点  
             * 处理完成之后Document会保存到XmlConfigurationProvider#documents list集合中 
             * include file路径会保存到XmlConfigurationProvider#loadedFileUrls set集合中  
             * 从代码中发现 include file属性中 可以使用通配符 "*" 
             */  
            /** StrutsXmlConfigurationProvider 是 XmlConfigurationProvider的子类 */  
            /** StrutsXmlConfigurationProvider struts*.xml */  
            containerProvider.init(this);  
            //针对"bean","constant","unknown-handler-stack"节点  不包括"package"节点   解析xml   
            //每一个bean 对应一个LocatableFactory  LocatableFactory保存了bean的定义  
            //bean定义 保存到ContainerBuilder#factories map集合中   
            //配置文件中定义的常量  保存到props中  
            containerProvider.register(builder, props);  
        }  
        //将常量保存到ContainerBuilder#factories map集合中   
        //每一个常量对应一个LocatableConstantFactory  
        props.setConstants(builder);  
        builder.factory(Configuration.class, new Factory<Configuration>() {  
            public Configuration create(Context context) throws Exception {  
                return DefaultConfiguration.this;  
            }  
        });  
  
        ActionContext oldContext = ActionContext.getContext();  
        try {  
            //创建辅助容器 ContainerImpl并且 实例化 struts一些核心类   
            Container bootstrap = createBootstrapContainer();  
            setContext(bootstrap);  
              
            //主容器 这是一个全局变量   
            container = builder.create(false);  
            setContext(container);  
            objectFactory = container.getInstance(ObjectFactory.class);  
  
            // Process the configuration providers first  
            for (final ContainerProvider containerProvider : providers) {  
                if (containerProvider instanceof PackageProvider) {  
                    //com.opensymphony.xwork2.config.providers.XmlConfigurationProvider#setObjectFactory(ObjectFactory)  
                    container.inject(containerProvider);  
                    //解析  xml  package节点  
                    //保存packageContexts map集合中  
                    //com.opensymphony.xwork2.config.providers.XmlConfigurationProvider  line 481  
                    ((PackageProvider) containerProvider).loadPackages();  
                    packageProviders.add((PackageProvider) containerProvider);  
                }  
            }  
  
            // Then process any package providers from the plugins  
            Set<String> packageProviderNames = container.getInstanceNames(PackageProvider.class);  
            if (packageProviderNames != null) {  
                for (String name : packageProviderNames) {  
                    PackageProvider provider = container.getInstance(PackageProvider.class, name);  
                    provider.init(this);  
                    provider.loadPackages();  
                    packageProviders.add(provider);  
                }  
            }  
            //TODO  
            rebuildRuntimeConfiguration();  
        } finally {  
            if (oldContext == null) {  
                ActionContext.setContext(null);  
            }  
        }  
        return packageProviders;  
    }  

StrutsXmlConfigurationProvider的init方法 具体在父类XmlConfigurationProvider中实现

public void init(Configuration configuration) {  
    this.configuration = configuration;  
    this.includedFileNames = configuration.getLoadedFileNames();  
    // configFileName ->struts.xml  
    //1.递归处理include节点  
    //2.生成Document 集合  
    loadDocuments(configFileName);  
}  

loadDocuments方法中调用了loadConfigurationFiles方法  返回一个Document集合

private void loadDocuments(String configFileName) {  
    loadedFileUrls.clear();  
     //List<Document> documents  
    documents = loadConfigurationFiles(configFileName, null);  
} 

loadConfigurationFiles方法 递归处理include节点 最终生成Document集合

private List<Document> loadConfigurationFiles(String fileName, Element includeElement) {  
        List<Document> docs = new ArrayList<Document>();  
        List<Document> finalDocs = new ArrayList<Document>();  
        //防止include重复引入  
        if (!includedFileNames.contains(fileName)) {  
            if (LOG.isDebugEnabled()) {  
                LOG.debug("Loading action configurations from: " + fileName);  
            }  
            includedFileNames.add(fileName);  
            Iterator<URL> urls = null;  
            InputStream is = null;  
            IOException ioException = null;  
            try {  
                urls = getConfigurationUrls(fileName);  
            } catch (IOException ex) {  
                ioException = ex;  
            }  
  
            if (urls == null || !urls.hasNext()) {  
                if (errorIfMissing) {  
                    throw new ConfigurationException("Could not open files of the name " + fileName, ioException);  
                } else {  
                    LOG.info("Unable to locate configuration files of the name " + fileName + ", skipping");  
                    return docs;  
                }  
            }  
            URL url = null;  
            while (urls.hasNext()) {  
                try {  
                    url = urls.next();  
                    is = FileManager.loadFile(url);  
                    InputSource in = new InputSource(is);  
                    in.setSystemId(url.toString());  
                    //生成Document对象  
                    docs.add(DomHelper.parse(in, dtdMappings));  
                } catch (XWorkException e) {  
                    if (includeElement != null) {  
                        throw new ConfigurationException("Unable to load " + url, e, includeElement);  
                    } else {  
                        throw new ConfigurationException("Unable to load " + url, e);  
                    }  
                } catch (Exception e) {  
                    final String s = "Caught exception while loading file " + fileName;  
                    throw new ConfigurationException(s, e, includeElement);  
                } finally {  
                    if (is != null) {  
                        try {  
                            is.close();  
                        } catch (IOException e) {  
                            LOG.error("Unable to close input stream", e);  
                        }  
                    }  
                }  
            }  
            //sort the documents, according to the "order" attribute  
            Collections.sort(docs, new Comparator<Document>() {  
                public int compare(Document doc1, Document doc2) {  
                    return XmlHelper.getLoadOrder(doc1).compareTo(XmlHelper.getLoadOrder(doc2));  
                }  
            });  
            for (Document doc : docs) {  
                Element rootElement = doc.getDocumentElement();  
                NodeList children = rootElement.getChildNodes();  
                int childSize = children.getLength();  
                for (int i = 0; i < childSize; i++) {  
                    Node childNode = children.item(i);  
                    if (childNode instanceof Element) {  
                        Element child = (Element) childNode;  
                        final String nodeName = child.getNodeName();  
                        if ("include".equals(nodeName)) {  
                            String includeFileName = child.getAttribute("file");  
                            //可以使用通配符匹配    
                            if (includeFileName.indexOf('*') != -1) {  
                                ClassPathFinder wildcardFinder = new ClassPathFinder();  
                                wildcardFinder.setPattern(includeFileName);  
                                Vector<String> wildcardMatches = wildcardFinder.findMatches();  
                                for (String match : wildcardMatches) {  
                                    //递归处理include节点  
                                    finalDocs.addAll(loadConfigurationFiles(match, child));  
                                }  
                            } else {  
                                //递归处理include节点  
                                finalDocs.addAll(loadConfigurationFiles(includeFileName, child));  
                            }  
                        }  
                    }  
                }  
                finalDocs.add(doc);  
                loadedFileUrls.add(url.toString());  
            }  
        }  
        return finalDocs;  
    }  

StrutsXmlConfigurationProvider的register方法 主要在父类 XmlConfigurationProvider中实现
1.遍历init方法中生成的Document 集合  解析xml文件中定义的bean,constant常量节点 不会处理package节点
2.解析bean节点的值 包装成LocatableFactory对象  注册到ContainerBuilder中factories map集合中
3.解析constant节点的值 保存到ContainerProperties 对象中
XmlConfigurationProvider 的register  这里只解析 bean , constant节点

public void register(ContainerBuilder containerBuilder, LocatableProperties props) throws ConfigurationException {  
    Map<String, Node> loadedBeans = new HashMap<String, Node>();  
    for (Document doc : documents) {  
        Element rootElement = doc.getDocumentElement();  
        NodeList children = rootElement.getChildNodes();  
        int childSize = children.getLength();  
        for (int i = 0; i < childSize; i++) {  
            Node childNode = children.item(i);  
            if (childNode instanceof Element) {  
                Element child = (Element) childNode;  
                final String nodeName = child.getNodeName();  
                //解析bean节点  
                if ("bean".equals(nodeName)) {  
                    String type = child.getAttribute("type");  
                    String name = child.getAttribute("name");  
                    String impl = child.getAttribute("class");  
                    String onlyStatic = child.getAttribute("static");  
                    String scopeStr = child.getAttribute("scope");  
                    boolean optional = "true".equals(child.getAttribute("optional"));  
                    Scope scope = Scope.SINGLETON;  
                    if ("default".equals(scopeStr)) {  
                        scope = Scope.DEFAULT;  
                    } else if ("request".equals(scopeStr)) {  
                        scope = Scope.REQUEST;  
                    } else if ("session".equals(scopeStr)) {  
                        scope = Scope.SESSION;  
                    } else if ("singleton".equals(scopeStr)) {  
                        scope = Scope.SINGLETON;  
                    } else if ("thread".equals(scopeStr)) {  
                        scope = Scope.THREAD;  
                    }  
                    if (StringUtils.isEmpty(name)) {  
                        name = Container.DEFAULT_NAME;  
                    }  
                    try {  
                        Class cimpl = ClassLoaderUtil.loadClass(impl, getClass());  
                        Class ctype = cimpl;  
                        if (StringUtils.isNotEmpty(type)) {  
                            ctype = ClassLoaderUtil.loadClass(type, getClass());  
                        }  
                        if ("true".equals(onlyStatic)) {  
                            // Force loading of class to detect no class def found exceptions  
                            cimpl.getDeclaredClasses();  
                            containerBuilder.injectStatics(cimpl);  
                        } else {  
                            // beanName + class 构成唯一约束   
                            if (containerBuilder.contains(ctype, name)) {  
                                //用loadedBeans map集合检查是否有重复配置的bean  
                                Location loc = LocationUtils.getLocation(loadedBeans.get(ctype.getName() + name));  
                                if (throwExceptionOnDuplicateBeans) {  
                                    throw new ConfigurationException("Bean type " + ctype + " with the name " + name + " has already been loaded by " + loc, child);  
                                }  
                            }  
                            // Force loading of class to detect no class def found exceptions  
                            cimpl.getDeclaredConstructors();  
  
                            if (LOG.isDebugEnabled()) {  
                                LOG.debug("Loaded type:" + type + " name:" + name + " impl:" + impl);  
                            }  
                            //LocatableFactory 类似spring中 BeanDefinition   
                            //bean定义 保存到ContainerBuilder#factories map集合中  
                            //目前为止  并未真正实例化bean  
                            containerBuilder.factory(ctype, name, new LocatableFactory(name, ctype, cimpl, scope, childNode), scope);  
                        }  
                        //loadedBeans 检查重复配置的bean  
                        loadedBeans.put(ctype.getName() + name, child);  
                    } catch (Throwable ex) {  
                        if (!optional) {  
                            throw new ConfigurationException("Unable to load bean: type:" + type + " class:" + impl, ex, childNode);  
                        } else {  
                            LOG.debug("Unable to load optional class: " + ex);  
                        }  
                    }  
                    //constant常量节点  
                } else if ("constant".equals(nodeName)) {  
                    String name = child.getAttribute("name");  
                    String value = child.getAttribute("value");  
                    //ContainerProperties ->props  
                    props.setProperty(name, value, childNode);  
                } else if (nodeName.equals("unknown-handler-stack")) {  
                    List<UnknownHandlerConfig> unknownHandlerStack = new ArrayList<UnknownHandlerConfig>();  
                    NodeList unknownHandlers = child.getElementsByTagName("unknown-handler-ref");  
                    int unknownHandlersSize = unknownHandlers.getLength();  
                    for (int k = 0; k < unknownHandlersSize; k++) {  
                        Element unknownHandler = (Element) unknownHandlers.item(k);  
                        unknownHandlerStack.add(new UnknownHandlerConfig(unknownHandler.getAttribute("name")));  
                    }  
                    if (!unknownHandlerStack.isEmpty()) configuration.setUnknownHandlerStack(unknownHandlerStack);  
                }  
            }  
        }  
    }  
}  

XmlConfigurationProvider的loadPackages方法  解析package节点下的所有子节点interceptor ,ResultType等等
保存到DefaultConfiguration packageContexts map集合中

public void loadPackages() throws ConfigurationException {  
        List<Element> reloads = new ArrayList<Element>();  
        for (Document doc : documents) {  
            Element rootElement = doc.getDocumentElement();  
            NodeList children = rootElement.getChildNodes();  
            int childSize = children.getLength();  
            for (int i = 0; i < childSize; i++) {  
                Node childNode = children.item(i);  
                if (childNode instanceof Element) {  
                    Element child = (Element) childNode;  
                    final String nodeName = child.getNodeName();  
                    if ("package".equals(nodeName)) {  
                        //解析package节点  包装成PackageConfig对象  
                        PackageConfig cfg = addPackage(child);  
                        if (cfg.isNeedsRefresh()) {  
                            reloads.add(child);  
                        }  
                    }  
                }  
            }  
            //空实现  扩展时用  
            loadExtraConfiguration(doc);  
        }  
  
        if (reloads.size() > 0) {  
            reloadRequiredPackages(reloads);  
        }  
        for (Document doc : documents) {  
            //空实现  扩展时用  
            loadExtraConfiguration(doc);  
        }  
        documents.clear();  
        configuration = null;  
    } 

package节点下的所有子节点

protected PackageConfig addPackage(Element packageElement) throws ConfigurationException {  
    PackageConfig.Builder newPackage = buildPackageContext(packageElement);  
    if (newPackage.isNeedsRefresh()) {  
        return newPackage.build();  
    }  
    //处理所有的ResultType 包括自定义的 , strust-default.xml中定义的  
    addResultTypes(newPackage, packageElement);  
    //interceptor节点  
    loadInterceptors(newPackage, packageElement);  
    //default-interceptor-ref  
    loadDefaultInterceptorRef(newPackage, packageElement);  
    //default-class-ref节点  
    loadDefaultClassRef(newPackage, packageElement);  
    //全局result global-results节点  
    loadGlobalResults(newPackage, packageElement);  
    //global-exception-mappings节点 异常处理   
    loadGobalExceptionMappings(newPackage, packageElement);  
  
    NodeList actionList = packageElement.getElementsByTagName("action");  
    for (int i = 0; i < actionList.getLength(); i++) {  
        Element actionElement = (Element) actionList.item(i);  
        // action节点 result节点处理  
        addAction(actionElement, newPackage);  
    }  
    //default-action-ref  
    loadDefaultActionRef(newPackage, packageElement);  
    PackageConfig cfg = newPackage.build();  
    //TODO 保存到Map<string packageconfig=""> packageContexts 集合中  
    configuration.addPackageConfig(cfg.getName(), cfg);  
    return cfg;  
}

最后整理解析的ActionConfig Map集合[DefaultConfiguration#packageContexts]  最终已Map<nameSpace,Map<actionName, ActionConfig>>形式存储

public void rebuildRuntimeConfiguration() {  
    runtimeConfiguration = buildRuntimeConfiguration();  
} 


protected synchronized RuntimeConfiguration buildRuntimeConfiguration() throws ConfigurationException {  
    Map<String, Map<String, ActionConfig>> namespaceActionConfigs = new LinkedHashMap<String, Map<String, ActionConfig>>();  
    Map<String, String> namespaceConfigs = new LinkedHashMap<String, String>();  
  
    for (PackageConfig packageConfig : packageContexts.values()) {  
  
        if (!packageConfig.isAbstract()) {  
            String namespace = packageConfig.getNamespace();  
            Map<String, ActionConfig> configs = namespaceActionConfigs.get(namespace);  
  
            if (configs == null) {  
                configs = new LinkedHashMap<String, ActionConfig>();  
            }  
  
            Map<String, ActionConfig> actionConfigs = packageConfig.getAllActionConfigs();  
  
            for (Object o : actionConfigs.keySet()) {  
                String actionName = (String) o;  
                ActionConfig baseConfig = actionConfigs.get(actionName);  
                //这里设置action的拦截器  
                //TODO buildFullActionConfig  
                configs.put(actionName, buildFullActionConfig(packageConfig, baseConfig));  
            }  
            //key -> nameSpace  
            //value - > <actionName, ActionConfig>  ,ActionConfig包含了拦截器  
            namespaceActionConfigs.put(namespace, configs);  
            if (packageConfig.getFullDefaultActionRef() != null) {  
                namespaceConfigs.put(namespace, packageConfig.getFullDefaultActionRef());  
            }  
        }  
    }  
    return new RuntimeConfigurationImpl(namespaceActionConfigs, namespaceConfigs);  
}  

解析完成后,  最终会保存到DefaultConfiguration  runtimeConfiguration变量中
初始化顺序图:


分享到:
评论

相关推荐

    struts2-json-plugin-2.3.24-API文档-中文版.zip

    赠送jar包:struts2-json-plugin-2.3.24.jar; 赠送原API文档:struts2-json-plugin-2.3.24-javadoc.jar; 赠送源代码:struts2-json-plugin-2.3.24-sources.jar; 赠送Maven依赖信息文件:struts2-json-plugin-...

    struts2-json-plugin源码

    3. **JSON插件配置**:在`struts-plugin.xml`配置文件中,会注册JSON插件,声明结果类型和其他相关设置,如启用GZIP压缩、排除某些字段等。 4. **拦截器**:Struts2的拦截器机制允许在Action调用前后执行特定逻辑。...

    struts2-core.jar

    struts2-core-2.0.1.jar, struts2-core-2.0.11.1.jar, struts2-core-2.0.11.2.jar, struts2-core-2.0.11.jar, struts2-core-2.0.12.jar, struts2-core-2.0.14.jar, struts2-core-2.0.5.jar, struts2-core-2.0.6.jar,...

    struts2-core-2.0.11源码

    在研究源码时,理解以上这些核心概念和组件的工作原理,可以帮助你深入掌握Struts2框架,从而更好地进行开发和优化。同时,由于源码可能存在错误,学习过程中需要具备一定的问题排查能力,利用IDE的调试工具逐步跟踪...

    struts2-ssl-plugin-1.2.1.jar

    struts2-ssl-plugin-1.2.1.jar

    json-lib-2.1.jar和struts2-json-plugin-2.1.8.1.jar

    `struts2-json-plugin-2.1.8.1.jar` 则是Struts 2框架的一个插件,主要用于增强Struts 2对JSON的支持。Struts 2是一款非常流行的MVC(Model-View-Controller)框架,用于构建企业级的Java Web应用程序。这个插件允许...

    struts2-core-2.2.3.1-sources.jar

    struts2-core-2.2.3.1-sources.jar struts2-core-2.2.3.1-sources.jar struts2-core-2.2.3.1-sources.jar

    struts2-core-2.3.7源码

    1. **StrutsPrepareAndExecuteFilter**: 这是Struts2的过滤器,负责初始化框架并处理请求。 2. **ActionContext**: 包含了当前请求的所有上下文信息,如session、request、response、value stack等。 3. **...

    struts2-spring-plugin-2.3.4.jar

    通过Struts 2-Spring 插件,我们可以将Struts 2 的Action 对象交给Spring 来管理,Spring 负责初始化、配置和销毁这些对象。这样,Action 类不再需要自己去创建依赖的对象,而是通过构造函数或setter 方法接收Spring...

    struts2-convention-plugin-2.3.15.1.jar

    struts2-convention-plugin-2.3.15.1.jar

    Struts2源码分析--请求处理.pdf

    Struts2源码分析--请求处理.pdf

    struts2漏洞s2-045,不升级jar版本的修补方法,已验证.docx

    3. 解压找到位置 org/apache/struts2/dispatcher/multipart:然后,我们需要解压源码包,找到 org/apache/struts2/dispatcher/multipart 目录。 4. 复制文件 JakartaMultiPartRequest.java、...

    struts2-json-plugin-2.3.8.jar

    这个插件主要的功能是让Struts2应用程序能够轻松地处理JSON(JavaScript Object Notation)数据格式,使得Web应用可以方便地进行JSON序列化和反序列化,从而实现与前端的Ajax交互。 Struts2是一个基于Model-View-...

    Struts2_s2-016&017&ognl2.6.11_patch漏洞补丁

    -- 为修复struts2 s2-016、s2-017漏洞,重写DefaultActionMapper --&gt; &lt;bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="myDefaultActionMapper" class=...

    struts2-core-2.2.1-sources.jar

    struts2-core-2.2.1-sources.jar 源码,学strut2源码时能用到的

    struts2-jfreechart-plugin-2.1.8.1.jar

    struts2-jfreechart-plugin-2.1.8.1.jar

    Struts2源码分析--请求处理[汇编].pdf

    Struts2源码分析--请求处理[汇编].pdf

    struts2-spring-plugin-2.3.24.1.jar

    最新struts2-spring-plugin-2.3.24.1.jar

    struts2-core-2.1.6.jar

    struts2-core-2.1.6.jarstruts2-core-2.1.6.jarstruts2-core-2.1.6.jarstruts2-core-2.1.6.jarstruts2-core-2.1.6.jarstruts2-core-2.1.6.jarstruts2-core-2.1.6.jarstruts2-core-2.1.6.jarstruts2-core-2.1.6.jar...

    struts2-core-2.0.12.jar

    Struts2支持多语言环境,通过资源包(Properties文件)可以轻松实现国际化和本地化。 **9. 自动表单验证** Struts2提供了一套强大的表单验证机制,可以在服务器端对用户输入的数据进行验证,并将错误信息反馈给用户...

Global site tag (gtag.js) - Google Analytics