- 浏览: 76110 次
- 性别:
- 来自: 沈阳
文章分类
- 全部博客 (75)
- spring (5)
- hibernate (4)
- struts (1)
- ibatis (1)
- others (3)
- java (6)
- 整合 (5)
- linux (4)
- easyui (1)
- javascript (4)
- web (11)
- eclipse (0)
- freemarker (0)
- maven (0)
- mongodb (0)
- spring security (1)
- log4j (0)
- jbpm (1)
- jms (3)
- redis (1)
- mysql (3)
- solr (3)
- nginx (2)
- rabbitmq (6)
- druid (1)
- jenkins (2)
- vmware (1)
- memcached (2)
- idea (1)
- elasticsearch (2)
最新评论
StrutsPrepareAndExecuteFilter实现了Filter接口 init方法为初始化入口
StrutsPrepareAndExecuteFilter init方法
InitOperations 类似与一个Delegate 主要负责实例化Dispatche 再把初始化操作转交给Dispatche init处理
Dispatcher init方法 1.针对配置文件 注册不同的加载器 保存到ConfigurationManager类中的一个变量中 2.创建容器 解析xml
ConfigurationManager 主要管理 创建的各种加载器
Dispatcher的 createConfigurationManager方法
1.default.properties 属性文件加载器
2.创建struts相关文件加载器 StrutsXmlConfigurationProvider
3.web.xml扩展的ContainerProviders加载器 实例化
init_PreloadConfiguration 方法主要完成创建容器, 解析xml动作
init_PreloadConfiguration 方法中调用了 ConfigurationManager的getConfiguration 方法
DefaultConfiguration的reloadContainer方法 会去执行已注册的各种加载器 ,和创建容器
StrutsXmlConfigurationProvider的init方法 具体在父类XmlConfigurationProvider中实现
loadDocuments方法中调用了loadConfigurationFiles方法 返回一个Document集合
loadConfigurationFiles方法 递归处理include节点 最终生成Document集合
StrutsXmlConfigurationProvider的register方法 主要在父类 XmlConfigurationProvider中实现
1.遍历init方法中生成的Document 集合 解析xml文件中定义的bean,constant常量节点 不会处理package节点
2.解析bean节点的值 包装成LocatableFactory对象 注册到ContainerBuilder中factories map集合中
3.解析constant节点的值 保存到ContainerProperties 对象中
XmlConfigurationProvider 的register 这里只解析 bean , constant节点
XmlConfigurationProvider的loadPackages方法 解析package节点下的所有子节点interceptor ,ResultType等等
保存到DefaultConfiguration packageContexts map集合中
package节点下的所有子节点
最后整理解析的ActionConfig Map集合[DefaultConfiguration#packageContexts] 最终已Map<nameSpace,Map<actionName, ActionConfig>>形式存储
解析完成后, 最终会保存到DefaultConfiguration runtimeConfiguration变量中
初始化顺序图:
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变量中
初始化顺序图:
相关推荐
赠送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-...
3. **JSON插件配置**:在`struts-plugin.xml`配置文件中,会注册JSON插件,声明结果类型和其他相关设置,如启用GZIP压缩、排除某些字段等。 4. **拦截器**:Struts2的拦截器机制允许在Action调用前后执行特定逻辑。...
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框架,从而更好地进行开发和优化。同时,由于源码可能存在错误,学习过程中需要具备一定的问题排查能力,利用IDE的调试工具逐步跟踪...
struts2-ssl-plugin-1.2.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
1. **StrutsPrepareAndExecuteFilter**: 这是Struts2的过滤器,负责初始化框架并处理请求。 2. **ActionContext**: 包含了当前请求的所有上下文信息,如session、request、response、value stack等。 3. **...
通过Struts 2-Spring 插件,我们可以将Struts 2 的Action 对象交给Spring 来管理,Spring 负责初始化、配置和销毁这些对象。这样,Action 类不再需要自己去创建依赖的对象,而是通过构造函数或setter 方法接收Spring...
struts2-convention-plugin-2.3.15.1.jar
Struts2源码分析--请求处理.pdf
3. 解压找到位置 org/apache/struts2/dispatcher/multipart:然后,我们需要解压源码包,找到 org/apache/struts2/dispatcher/multipart 目录。 4. 复制文件 JakartaMultiPartRequest.java、...
这个插件主要的功能是让Struts2应用程序能够轻松地处理JSON(JavaScript Object Notation)数据格式,使得Web应用可以方便地进行JSON序列化和反序列化,从而实现与前端的Ajax交互。 Struts2是一个基于Model-View-...
-- 为修复struts2 s2-016、s2-017漏洞,重写DefaultActionMapper --> <bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="myDefaultActionMapper" class=...
struts2-core-2.2.1-sources.jar 源码,学strut2源码时能用到的
struts2-jfreechart-plugin-2.1.8.1.jar
Struts2源码分析--请求处理[汇编].pdf
最新struts2-spring-plugin-2.3.24.1.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支持多语言环境,通过资源包(Properties文件)可以轻松实现国际化和本地化。 **9. 自动表单验证** Struts2提供了一套强大的表单验证机制,可以在服务器端对用户输入的数据进行验证,并将错误信息反馈给用户...