版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kk121150/article/details/78169677
FilterDispatcher是struts2.0.x到2.1.2版本的核心过滤器.!
StrutsPrepareAndExecuteFilter是自2.1.3开始就替代了FilterDispatcher的
方法摘要
void |
destroy() 继承自Filter,用于资源释放 |
void |
doFilter(ServletRequest req,ServletResponse res,FilterChain chain) 继承自Filter,执行方法 |
void |
init(FilterConfig filterConfig) 继承自Filter,初始化参数 |
protected void |
postInit(Dispatcher dispatcher,FilterConfig filterConfig) Callback for post initialization(一个空的方法,用于方法回调初始化) |
protected List<Pattern> |
excludedPatterns |
protected ExecuteOperations |
execute |
protected PrepareOperations |
prepare |
StrutsPrepareAndExecuteFilter类继承与Filter,所以大体结构和普通Filter类似:
public class StrutsPrepareAndExecuteFilter implements StrutsStatics, Filter {
protected PrepareOperations prepare;
protected ExecuteOperations execute;
protected List<Pattern> excludedPatterns = null;
public void init(FilterConfig filterConfig) {
Dispatcher dispatcher = null;
try {
FilterHostConfig config = new FilterHostConfig(filterConfig); //读取配置文件信息,封装到config
dispatcher = init.initDispatcher(config); //根据config创建dispatcher对象
...
prepare = new PrepareOperations(dispatcher); //根据dispatcher创建prepare对象(包括准备的一些操作)
execute = new ExecuteOperations(dispatcher); //根据dispatcher创建execute对象(包括执行的一些操作)
postInit(dispatcher, filterConfig); //回调空的postInit函数
} finally {
...
}
}
/**
* Callback for post initialization
*/
protected void postInit(Dispatcher dispatcher, FilterConfig filterConfig) {
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain){
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try {
prepare.createActionContext(request, response); //创建ActionContext对象!!!存储request、session、application、parameters等相关信息
execute.executeAction(request, response, mapping); //执行ActionContext(创建ActionProxy对象并嵌入一系列的拦截器,调用Action)
}
} finally {
}
}
public void destroy() {
prepare.cleanupDispatcher();
}
}
Filter方法调用顺序为由init—>doFilter—>destroy顺序调用。
init方法
public void init(FilterConfig filterConfig) throws ServletException {
//创建一个InitOperations初始化操作的对象
InitOperations init = new InitOperations();
try {
//封装filterConfig,其中有个主要方法getInitParameterNames将参数名字以String格式存储在List中
FilterHostConfig config = new FilterHostConfig(filterConfig);
// 初始化struts内部日志
init.initLogging(config);
//创建dispatcher对象,并读取配置文件
Dispatcher dispatcher = init.initDispatcher(config);
init.initStaticContentLoader(config, dispatcher);
//初始化类属性:prepare 、execute
prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
//回调空的postInit方法
postInit(dispatcher, filterConfig);
} finally {
init.cleanup();
}
}
public class FilterHostConfig implements HostConfig {
private FilterConfig config;
/*
* 构造函数
*/
public FilterHostConfig(FilterConfig config) {
this.config = config;
}
//根据init-param配置的param-name获取param-value的值
public String getInitParameter(String key) {
return config.getInitParameter(key);
}
//返回初始化参数名的List
public Iterator<String> getInitParameterNames() {
return MakeIterator.convert(config.getInitParameterNames());
}
public ServletContext getServletContext() {
return config.getServletContext();
}
}
创建并初始化Dispatcher
public Dispatcher initDispatcher(HostConfig filterConfig) {
// 创建dispatcher对象,将参数传递dispatcher全局变量
Dispatcher dispatcher = createDispatcher(filterConfig);
// 初始化配置文件/读取配置文件
dispatcher.init();
return dispatcher;
}
创建Dispatcher,会读取 filterConfig 中的配置信息,将配置信息解析出来,封装成为一个Map,然后根绝servlet上下文和参数Map构造Dispatcher :
createDispatcher方法。创建Dispatcher,会读取 filterConfig中的配置信息。
private Dispatcher createDispatcher(HostConfig filterConfig) {
Map<String, String> params = new HashMap<String, String>();
// 获得在web.xml中所有的配置文件,将参数放入params Map集合中
for (Iterator e = filterConfig.getInitParameterNames(); e.hasNext();) {
String name = (String) e.next();
String value = filterConfig.getInitParameter(name);
params.put(name, value);
}
// 创建Dispatcher 对象,将ServletContext(),将参数赋给Dispatcher的全局私有变量中
return new Dispatcher(filterConfig.getServletContext(), params);
}
Disptcher的init方法,init方法里就是初始读取一些配置文件等,加载struts2的相关配置文件,将按照顺序逐一加载:default.properties,struts-default.xml,struts-plugin.xml,struts.xml,
*初始化过程中依次加载如下配置文件
*/
public void init() {
if (configurationManager == null) {
configurationManager = new ConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);
}
try {
//加载org/apache/struts2/default.properties
init_DefaultProperties(); // [1]
//加载struts-default.xml,struts-plugin.xml,struts.xml
init_TraditionalXmlConfigurations(); // [2]
init_LegacyStrutsProperties(); // [3]
//用户自己实现的ConfigurationProviders类
init_CustomConfigurationProviders(); // [5]
//Filter的初始化参数
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);
}
}
doFilter方法
doFilter是过滤器的执行方法,它拦截提交的HttpServletRequest请求,HttpServletResponse响应,作为strtus2的核心拦截器,在doFilter里面到底做了哪些工作,我们将逐行解读其源码,源码如下:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
//父类向子类转:强转为http请求、响应
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try {
//设置编码和国际化
prepare.setEncodingAndLocale(request, response);
//创建Action上下文(重点)
prepare.createActionContext(request, response);
prepare.assignDispatcherToThread();
if ( excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
chain.doFilter(request, response);
} else {
request = prepare.wrapRequest(request);
ActionMapping mapping = prepare.findActionMapping(request, response, true);
if (mapping == null) {
boolean handled = execute.executeStaticResourceRequest(request, response);
if (!handled) {
chain.doFilter(request, response);
}
} else {
execute.executeAction(request, response, mapping);
}
}
} finally {
prepare.cleanupRequest(request);
}
}
Action上下文创建(重点)
ActionContext是一个容器,这个容易主要存储request、session、application、parameters等相关信息.ActionContext是一个线程的本地变量,这意味着不同的action之间不会共享ActionContext,所以也不用考虑线程安全问题。其实质是一个Map,key是标示request、session、……的字符串,值是其对应的对象:
//创建ActionContext,初始化thread local
public ActionContext createActionContext(HttpServletRequest request, HttpServletResponse response) {
ActionContext ctx;
Integer counter = 1;
Integer oldCounter = (Integer) request.getAttribute(CLEANUP_RECURSION_COUNTER);
if (oldCounter != null) {
counter = oldCounter + 1;
}
//从ThreadLocal中获取此ActionContext变量
ActionContext oldContext = ActionContext.getContext();
if (oldContext != null) {
// detected existing context, so we are probably in a forward
ctx = new ActionContext(new HashMap<String, Object>(oldContext.getContextMap()));
} else {
ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();
stack.getContext().putAll(dispatcher.createContextMap(request, response, null, servletContext));
//stack.getContext()返回的是一个Map<String,Object>,根据此Map构造一个ActionContext
ctx = new ActionContext(stack.getContext());
}
request.setAttribute(CLEANUP_RECURSION_COUNTER, counter);
//将ActionContext保存ThreadLocal
ActionContext.setContext(ctx);
return ctx;
}
未完。。。