请求处理-struts2源码解析
struts2架框处理流程图
一、Struts2架框处理流程概序
请求首先通过Filter chain,Filter主要包括ActionContextCleanUp,它主要清理当前线程的ActionContext和 Dispatcher;FilterDispatcher主要通过AcionMapper来决定需要调用哪个Action。
ActionMapper取得了ActionMapping后,在Dispatcher的serviceAction方法里创建 ActionProxy,ActionProxy创建ActionInvocation,然后ActionInvocation调用 Interceptors,执行Action本身,创建Result并返回,当然,如果要在返回之前做些什么,可以实现 PreResultListener。
二、Struts2部分类介绍 (这部分从Struts2参考文档中翻译而来。)
1、ActionMapper
ActionMapper其实是HttpServletRequest和Action调用请求的一个映射,它屏蔽了Action对于Request等 java Servlet类的依赖。Struts2中它的默认实现类是DefaultActionMapper,ActionMapper很大的用处可以根据自己的需要来设计url格式,它自己也有Restful的实现,具体可以参考文档的docs\actionmapper.html。
2、ActionProxy&ActionInvocation
Action的一个代理,由ActionProxyFactory创建,它本身不包括Action实例,默认实现DefaultActionProxy 是由ActionInvocation持有Action实例。ActionProxy作用是如何取得Action,无论是本地还是远程。而 ActionInvocation的作用是如何执行Action,拦截器的功能就是在ActionInvocation中实现的。
3、ConfigurationProvider&Configuration
ConfigurationProvider就是Struts2中配置文件的解析器,Struts2中的配置文件主要是尤其实现类 XmlConfigurationProvider及其子类StrutsXmlConfigurationProvider来解析。
三、Struts2请求流程
1、客户端发送请求
2、请求先通过ActionContextCleanUp-->FilterDispatcher
3、FilterDispatcher通过ActionMapper来决定这个Request需要调用哪个Action
4、如果ActionMapper决定调用某个Action,FilterDispatcher把请求的处理交给ActionProxy,这儿已经转到它的Delegate--Dispatcher来执行
5、ActionProxy根据ActionMapping和ConfigurationManager找到需要调用的Action类
6、ActionProxy创建一个ActionInvocation的实例
7、ActionInvocation调用真正的Action,当然这涉及到相关拦截器的调用
8、Action执行完毕,ActionInvocation创建Result并返回,当然,如果要在返回之前做些什么,可以实现PreResultListener。添加PreResultListener可以在Interceptor中实现,不知道其它还有什么方式?
四、Struts2(2.1.2)部分源码阅读
从org.apache.struts2.dispatcher.FilterDispatcher开始
/** * Initializes the filter by creating a default dispatcher * and setting the default packages for static resources. * * @param filterConfig The filter configuration */ public void init(FilterConfig filterConfig) throws ServletException { try { this.filterConfig = filterConfig; //初始化日志工厂 initLogging(); //将Filter的配置中的所有属性都写入一个HashMap,并作为参数传递给Dispatcher的构造函数。 dispatcher = createDispatcher(filterConfig); dispatcher.init(); dispatcher.getContainer().inject(this); staticResourceLoader.setHostConfig(new FilterHostConfig(filterConfig)); } finally { ActionContext.setContext(null); } }
//读取配置文件中的信息保存至HashMap中
/** * Create a default {@link Dispatcher} that subclasses can override * with a custom Dispatcher, if needed. * * @param filterConfig Our FilterConfig * @return Initialized Dispatcher */ protected Dispatcher createDispatcher(FilterConfig filterConfig) { Map<String, String> params = new HashMap<String, String>(); for (Enumeration e = filterConfig.getInitParameterNames(); e.hasMoreElements();) { String name = (String) e.nextElement(); String value = filterConfig.getInitParameter(name); params.put(name, value); } return createDispatcher(filterConfig.getServletContext(), params); }
//创建一个Dispatcher(org.apache.struts2.dispatcher Dispatcher 类)
/** * Create a default {@link Dispatcher} that subclasses can override * with a custom Dispatcher, if needed. Called by * createDispatcher(FilterConfig). * * @param ctx ServletContext * @param params parameters from FilterConfig * @return Initialized Dispatcher */ protected Dispatcher createDispatcher(ServletContext ctx, Map<String, String> params) { return new Dispatcher(ctx, params); }
// Dispatcher类 init方法
/** * Load configurations, including both XML and zero-configuration strategies, * and update optional settings, including whether to reload configurations and resource files. */ public void init() { if (configurationManager == null) { configurationManager = createConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME); } try { init_DefaultProperties(); // [1] init_TraditionalXmlConfigurations(); // [2] init_LegacyStrutsProperties(); // [3] init_CustomConfigurationProviders(); // [5] init_FilterInitParameters() ; // [6] init_AliasStandardObjects() ; // [7] Container container = init_PreloadConfiguration(); container.inject(this); init_CheckConfigurationReloading(container); init_CheckWebLogicWorkaround(container); if (!dispatcherListeners.isEmpty()) { for (DispatcherListener l : dispatcherListeners) { l.dispatcherInitialized(this); } } } catch (Exception ex) { if (LOG.isErrorEnabled()) LOG.error("Dispatcher initialization failed", ex); throw new StrutsException(ex); } }
[1]、主要读取struts 默认配置default.properties文件中的参数(如:编码、后缀等一些基础配置参数)
private void init_DefaultProperties() { configurationManager.addConfigurationProvider(new DefaultPropertiesProvider()); }
[2]、这个方法主要是用于载入FilterDispatcher定义的config
如果读取初始化的HashMap列表中没有config这个属性,则struts会默认载入:
struts-default.xml,struts-plugin.xml,struts.xml 这三个文件,并且判断是否有xwork.xml,如果有则载入xwork的DTD,否则载入struts的DTD。
private void init_TraditionalXmlConfigurations() { String configPaths = initParams.get("config"); if (configPaths == null) { configPaths = DEFAULT_CONFIGURATION_PATHS; } String[] files = configPaths.split("\\s*[,]\\s*"); for (String file : files) { if (file.endsWith(".xml")) { if ("xwork.xml".equals(file)) { configurationManager.addContainerProvider(createXmlConfigurationProvider(file, false)); } else { configurationManager.addContainerProvider(createStrutsXmlConfigurationProvider(file, false, servletContext)); } } else { throw new IllegalArgumentException("Invalid configuration file name"); } } }
[3]、好像是初始化架框编码
private void init_LegacyStrutsProperties() { configurationManager.addContainerProvider(new LegacyPropertiesConfigurationProvider()); }
相关推荐
hgzhang 2020-05-06
白净垃圾桶 2020-05-04
playis 2020-04-18
郭大路路 2020-04-16
lenchio 2020-04-08
yixiaoqi00 2020-04-08
melonjj 2020-01-05
mmywcoco 2019-12-28
wangruiling 2014-06-13
yaoyao0 2014-06-01
YangHuiLiang 2014-05-20
方志朋 2019-12-22
xcguoyu 2014-01-18
方志朋 2015-04-30
殷龙飞 2014-06-24
zmysna 2016-12-16
89264255 2011-04-23
wuddny的blog 2014-12-04