分类: 框架 2014-01-10 10:13 1369人阅读
原文转载自:http://www.iteye.com/topic/829843
一、概述
Struts2的核心是一个Filter,Action可以脱离web容器,那么是什么让http请求和action关联在一起的,下面我们深入源码来分析下Struts2是如何工作的。
FilterDispatcher API 写道
Deprecated. Since Struts 2.1.3, use StrutsPrepareAndExecuteFilter instead or StrutsPrepareFilter and StrutsExecuteFilter if needing using the ActionContextCleanUp filter in addition to this one
鉴于常规情况官方推荐使用StrutsPrepareAndExecuteFilter替代FilterDispatcher,我们此文 将剖析StrutsPrepareAndExecuteFilter,其在工程中作为一个Filter配置在web.xml中,配置如下:
- < filter > < filter-name > </ filter-name > < filter-class ></ filter-class > </ filter > < filter-mapping > < filter-name > </ filter-name > < url-pattern > </ url-pattern > </ filter-mapping >
- <filter> <filter-name></filter-name> <filter-class></filter-class> </filter> <filter-mapping> <filter-name></filter-name> <url-pattern></url-pattern> </filter-mapping>
二、源码属性方法简介
下面我们研究下StrutsPrepareAndExecuteFilter源码,类的主要信息如下:
StrutsPrepareAndExecuteFilter与普通的Filter并无区别,方法除继承自Filter外,仅有一个回调方法,第三部分我
们将按照Filter方法调用顺序,由init—>doFilter—>destroy顺序地分析源码。
三、源码剖析
1、init方法
init是Filter第一个运行的方法,我们看下struts2的核心Filter在调用init方法初始化时做哪些工作:
-
public void throws
new
try
//封装filterConfig,其中有个主要方法getInitParameterNames将参数名字以String格式存储在List中
new
// 初始化struts内部日志
//<strong>创建dispatcher ,并初始化,这部分下面我们重点分析,初始化时加载那些资源</strong>
//初始化类属性:prepare 、execute
new
new
this
//回调空的postInit方法
finally
}
-
publicvoidthrows
new
try
//封装filterConfig,其中有个主要方法getInitParameterNames将参数名字以String格式存储在List中
new
// 初始化struts内部日志
//<strong>创建dispatcher ,并初始化,这部分下面我们重点分析,初始化时加载那些资源</strong>
//初始化类属性:prepare 、execute
new
new
this
//回调空的postInit方法
finally
}
首先看下FilterHostConfig ,源码如下:
-
public class implements
private
*构造函数
-
*/
public
this
* 根据init-param配置的param-name获取param-value的值
-
*/
public
return
* 返回初始化参数名的List
-
*/
public
return
public
return
}
-
publicclassimplements
private
*构造函数
-
*/
public
this
* 根据init-param配置的param-name获取param-value的值
-
*/
public
return
* 返回初始化参数名的List
-
*/
public
return
public
return
}
只有短短的几行代码,getInitParameterNames是这个类的核心,将Filter初始化参数名称有枚举类型转为Iterator。此类的主要作为是对filterConfig 封装。
重点来了,创建并初始化Dispatcher
创建Dispatcher,会读取 filterConfig 中的配置信息,将配置信息解析出来,封装成为一个Map,然后根绝servlet上下文和参数Map构造Dispatcher :
-
private
new
for
return new
}
-
private
new
for
returnnew
}
Dispatcher初始化,加载struts2的相关配置文件,将按照顺序逐一加载:default.properties,struts-default.xml,struts-plugin.xml,struts.xml,……
-
/**
-
*初始化过程中依次加载如下配置文件
-
*/
public void
if null
new
try
-
-
-
-
-
-
-
-
-
-
this
if
for
this
catch
if
throw new
}
-
/**
-
*初始化过程中依次加载如下配置文件
-
*/
publicvoid
ifnull
new
try
-
-
-
-
-
-
-
-
-
-
this
if
for
this
catch
if
thrownew
}
初始化default.properties,具体的初始化操作在DefaultPropertiesProvider类中
下面我们看下DefaultPropertiesProvider类源码:
-
public void
throws
null
try
new );
-
catch
throw new
}
-
publicvoid
throws
null
try
new);
-
catch
thrownew
}
其他的我们再次省略,大家可以浏览下各个初始化操作都加载了那些文件
3、doFilter方法
doFilter是过滤器的执行方法,它拦截提交的HttpServletRequest请求,HttpServletResponse响应,作为strtus2的核心拦截器,在doFilter里面到底做了哪些工作,我们将逐行解读其源码,源码如下:
-
public void throws
-
try
-
-
if null
else
true
if null
boolean
if
else
finally
}
-
publicvoidthrows
-
try
-
-
ifnull
else
true
ifnull
boolean
if
else
finally
}
setEncodingAndLocale调用了dispatcher方法的prepare方法:
-
/**
-
* Sets the request encoding and locale on the response
-
*/
public void
}
-
/**
-
* Sets the request encoding and locale on the response
-
*/
publicvoid
}
下面我们看下prepare方法,这个方法很简单只是设置了encoding 、locale ,做的只是一些辅助的工作:
-
public void
null
if null
null
if null
if null
try
catch
if null
if
);
-
publicvoid
null
ifnull
null
ifnull
ifnull
try
catch
ifnull
if
);
Action上下文创建(重点)
ActionContext是一个容器,这个容易主要存储request、session、application、parameters等相关信
息.ActionContext是一个线程的本地变量,这意味着不同的action之间不会共享ActionContext,所以也不用考虑线程安全问
题。其实质是一个Map,key是标示request、session、……的字符串,值是其对应的对象:
-
static new
Map<String, Object> context;
-
staticnew
Map<String, Object> context;
下面我们看下如何创建action上下文的,代码如下:
-
/**
-
*创建Action上下文,初始化thread local
-
*/
public
;
-
if null
;
-
-
if null
-
new new
else
class
null
-
new
-
return
}
-
/**
-
*创建Action上下文,初始化thread local
-
*/
public
;
-
ifnull
;
-
-
ifnull
-
newnew
else
class
null
-
new
-
return
}
上面代码中dispatcher.createContextMap,如何封装相关参数:
-
public
-
new
-
new
-
new
-
new
-
if null
return
}
-
public
-
new
-
new
-
new
-
new
-
ifnull
return
}
我们简单看下RequestMap,其他的省略。RequestMap类实现了抽象Map,故其本身是一个Map,主要方法实现:
-
//map的get实现
public
return
//map的put实现
public
null
return
}
-
//map的get实现
public
return
//map的put实现
public
null
return
}
下面是源码展示了如何执行Action控制器:
-
public voidthrows
public void
throws
-
-
boolean null
if
if null
if null
try
-
-
-
-
class
true false
-
-
if null
else
-
if
catch
-
if
if null
+ request.getQueryString();
-
else
catch
finally
}
-
publicvoidthrows
publicvoid
throws
-
-
booleannull
if
ifnull
ifnull
try
-
-
-
-
class
truefalse
-
-
ifnull
else
-
if
catch
-
if
ifnull
+ request.getQueryString();
-
else
catch
finally
}
文中对如何解析Struts.xml,如何将URL与action映射匹配为分析,有需要的我后续补全,因为
StrutsXmlConfigurationProvider继承XmlConfigurationProvider,并在register方法回调父
类的register,有兴趣的可以深入阅读下下XmlConfigurationProvider源码:
-
public void throws
if null class
class new
public throws
return
-
super
}
-
publicvoidthrows
ifnullclass
classnew
publicthrows
return
-
super
}
struts2-core-2.2.1.jar包中struts-2.1.7.dtd对于Action的定义如下:
-
<!ELEMENT action (param|result|interceptor-ref|exception-mapping)* >
>
-
<!ELEMENT action (param|result|interceptor-ref|exception-mapping)*>
>
从上述DTD中可见Action元素可以含有name 、class 、method 、converter 属性。
XmlConfigurationProvider解析struts.xml配置的Action元素:
-
protected void throws
);
-
);
-
);
-
if null
-
) ? methodName.trim() : null
-
-
if
-
className = packageContext.getDefaultClassRef();
-
} else {
-
className = ActionSupport.class.getName();
-
}*/
else
if
if
return
try
catch
throw new
new
if
) : ) + name +
}
-
protectedvoidthrows
);
-
);
-
);
-
ifnull
-
) ? methodName.trim() : null
-
-
if
-
className = packageContext.getDefaultClassRef();
-
} else {
-
className = ActionSupport.class.getName();
-
}*/
else
if
if
return
try
catch
thrownew
new
if
) : ) + name +
}
工作中不涉及Struts2,本周工作有个2天的空档期,稍微看了下struts2的文档,写了个demo,从源码的角度研究了下运行原理,如有分析不当请指出,我后续逐步完善更正,大家共同提高。
一、概述
Struts2的核心是一个Filter,Action可以脱离web容器,那么是什么让http请求和action关联在一起的,下面我们深入源码来分析下Struts2是如何工作的。
FilterDispatcher API 写道
Deprecated. Since Struts 2.1.3, use StrutsPrepareAndExecuteFilter
instead or StrutsPrepareFilter and StrutsExecuteFilter if needing using
the ActionContextCleanUp filter in addition to this one
鉴于常规情况官方推荐使用StrutsPrepareAndExecuteFilter替代FilterDispatcher,我们此文
将剖析StrutsPrepareAndExecuteFilter,其在工程中作为一个Filter配置在web.xml中,配置如下:
-
< filter >
< filter-name > </ filter-name >
< filter-class ></ filter-class >
</ filter >
< filter-mapping >
< filter-name > </ filter-name >
< url-pattern > </ url-pattern >
</ filter-mapping >
-
<filter>
<filter-name></filter-name>
<filter-class></filter-class>
</filter>
<filter-mapping>
<filter-name></filter-name>
<url-pattern></url-pattern>
</filter-mapping>
二、源码属性方法简介
下面我们研究下StrutsPrepareAndExecuteFilter源码,类的主要信息如下:
StrutsPrepareAndExecuteFilter与普通的Filter并无区别,方法除继承自Filter外,仅有一个回调方法,第三部分我
们将按照Filter方法调用顺序,由init—>doFilter—>destroy顺序地分析源码。
三、源码剖析
1、init方法
init是Filter第一个运行的方法,我们看下struts2的核心Filter在调用init方法初始化时做哪些工作:
-
public void throws
new
try
//封装filterConfig,其中有个主要方法getInitParameterNames将参数名字以String格式存储在List中
new
// 初始化struts内部日志
//<strong>创建dispatcher ,并初始化,这部分下面我们重点分析,初始化时加载那些资源</strong>
//初始化类属性:prepare 、execute
new
new
this
//回调空的postInit方法
finally
}
-
publicvoidthrows
new
try
//封装filterConfig,其中有个主要方法getInitParameterNames将参数名字以String格式存储在List中
new
// 初始化struts内部日志
//<strong>创建dispatcher ,并初始化,这部分下面我们重点分析,初始化时加载那些资源</strong>
//初始化类属性:prepare 、execute
new
new
this
//回调空的postInit方法
finally
}
首先看下FilterHostConfig ,源码如下:
-
public class implements
private
*构造函数
-
*/
public
this
* 根据init-param配置的param-name获取param-value的值
-
*/
public
return
* 返回初始化参数名的List
-
*/
public
return
public
return
}
-
publicclassimplements
private
*构造函数
-
*/
public
this
* 根据init-param配置的param-name获取param-value的值
-
*/
public
return
* 返回初始化参数名的List
-
*/
public
return
public
return
}
只有短短的几行代码,getInitParameterNames是这个类的核心,将Filter初始化参数名称有枚举类型转为Iterator。此类的主要作为是对filterConfig 封装。
重点来了,创建并初始化Dispatcher
创建Dispatcher,会读取 filterConfig 中的配置信息,将配置信息解析出来,封装成为一个Map,然后根绝servlet上下文和参数Map构造Dispatcher :
-
private
new
for
return new
}
-
private
new
for
returnnew
}
Dispatcher初始化,加载struts2的相关配置文件,将按照顺序逐一加载:default.properties,struts-default.xml,struts-plugin.xml,struts.xml,……
-
/**
-
*初始化过程中依次加载如下配置文件
-
*/
public void
if null
new
try
-
-
-
-
-
-
-
-
-
-
this
if
for
this
catch
if
throw new
}
-
/**
-
*初始化过程中依次加载如下配置文件
-
*/
publicvoid
ifnull
new
try
-
-
-
-
-
-
-
-
-
-
this
if
for
this
catch
if
thrownew
}
初始化default.properties,具体的初始化操作在DefaultPropertiesProvider类中
下面我们看下DefaultPropertiesProvider类源码:
-
public void
throws
null
try
new );
-
catch
throw new
}
-
publicvoid
throws
null
try
new);
-
catch
thrownew
}
其他的我们再次省略,大家可以浏览下各个初始化操作都加载了那些文件
3、doFilter方法
doFilter是过滤器的执行方法,它拦截提交的HttpServletRequest请求,HttpServletResponse响应,作为strtus2的核心拦截器,在doFilter里面到底做了哪些工作,我们将逐行解读其源码,源码如下:
-
public void throws
-
try
-
-
if null
else
true
if null
boolean
if
else
finally
}
-
publicvoidthrows
-
try
-
-
ifnull
else
true
ifnull
boolean
if
else
finally
}
setEncodingAndLocale调用了dispatcher方法的prepare方法:
-
/**
-
* Sets the request encoding and locale on the response
-
*/
public void
}
-
/**
-
* Sets the request encoding and locale on the response
-
*/
publicvoid
}
下面我们看下prepare方法,这个方法很简单只是设置了encoding 、locale ,做的只是一些辅助的工作:
-
public void
null
if null
null
if null
if null
try
catch
if null
if
);
-
publicvoid
null
ifnull
null
ifnull
ifnull
try
catch
ifnull
if
);
Action上下文创建(重点)
ActionContext是一个容器,这个容易主要存储request、session、application、parameters等相关信
息.ActionContext是一个线程的本地变量,这意味着不同的action之间不会共享ActionContext,所以也不用考虑线程安全问
题。其实质是一个Map,key是标示request、session、……的字符串,值是其对应的对象:
-
static new
Map<String, Object> context;
-
staticnew
Map<String, Object> context;
下面我们看下如何创建action上下文的,代码如下:
-
/**
-
*创建Action上下文,初始化thread local
-
*/
public
;
-
if null
;
-
-
if null
-
new new
else
class
null
-
new
-
return
}
-
/**
-
*创建Action上下文,初始化thread local
-
*/
public
;
-
ifnull
;
-
-
ifnull
-
newnew
else
class
null
-
new
-
return
}
上面代码中dispatcher.createContextMap,如何封装相关参数:
-
public
-
new
-
new
-
new
-
new
-
if null
return
}
-
public
-
new
-
new
-
new
-
new
-
ifnull
return
}
我们简单看下RequestMap,其他的省略。RequestMap类实现了抽象Map,故其本身是一个Map,主要方法实现:
-
//map的get实现
public
return
//map的put实现
public
null
return
}
-
//map的get实现
public
return
//map的put实现
public
null
return
}
下面是源码展示了如何执行Action控制器:
-
public voidthrows
public void
throws
-
-
boolean null
if
if null
if null
try
-
-
-
-
class
true false
-
-
if null
else
-
if
catch
-
if
if null
+ request.getQueryString();
-
else
catch
finally
}
-
publicvoidthrows
publicvoid
throws
-
-
booleannull
if
ifnull
ifnull
try
-
-
-
-
class
truefalse
-
-
ifnull
else
-
if
catch
-
if
ifnull
+ request.getQueryString();
-
else
catch
finally
}
文中对如何解析Struts.xml,如何将URL与action映射匹配为分析,有需要的我后续补全,因为
StrutsXmlConfigurationProvider继承XmlConfigurationProvider,并在register方法回调父
类的register,有兴趣的可以深入阅读下下XmlConfigurationProvider源码:
-
public void throws
if null class
class new
public throws
return
-
super
}
-
publicvoidthrows
ifnullclass
classnew
publicthrows
return
-
super
}
struts2-core-2.2.1.jar包中struts-2.1.7.dtd对于Action的定义如下:
-
<!ELEMENT action (param|result|interceptor-ref|exception-mapping)* >
>
-
<!ELEMENT action (param|result|interceptor-ref|exception-mapping)*>
>
从上述DTD中可见Action元素可以含有name 、class 、method 、converter 属性。
XmlConfigurationProvider解析struts.xml配置的Action元素:
-
protected void throws
);
-
);
-
);
-
if null
-
) ? methodName.trim() : null
-
-
if
-
className = packageContext.getDefaultClassRef();
-
} else {
-
className = ActionSupport.class.getName();
-
}*/
else
if
if
return
try
catch
throw new
new
if
) : ) + name +
}
-
protectedvoidthrows
);
-
);
-
);
-
ifnull
-
) ? methodName.trim() : null
-
-
if
-
className = packageContext.getDefaultClassRef();
-
} else {
-
className = ActionSupport.class.getName();
-
}*/
else
if
if
return
try
catch
thrownew
new
if
) : ) + name +
}
StrutsPrepareAndExecuteFilter
原文:http://www.cnblogs.com/splin/p/4270651.html