转: http://blog.csdn.net/accpsz/archive/2010/12/31/6108917.aspx
//
this is needed because the result will be executed, then control will return to the Interceptor, which will
//
return above and flow through again
if
(
!
executed) {
//
在Result返回之前调用preResultListeners
if
(preResultListeners
!=
null
) {
for
(Iterator iterator
=
preResultListeners.iterator();
iterator.hasNext();) {
PreResultListener listener
=
(PreResultListener) iterator.next();
String _profileKey
=
"
preResultListener:
"
;
try
{
UtilTimerStack.push(_profileKey);
listener.beforeResult(
this
, resultCode);
}
finally
{
UtilTimerStack.pop(_profileKey);
}
}
}
//
now execute the result, if we're supposed to
if
(proxy.getExecuteResult()) {
executeResult();
}
executed
=
true
;
}
return
resultCode;
}
finally
{
UtilTimerStack.pop(profileKey);
}
}
看程序中的if(interceptors.hasNext())语句,当然,interceptors里存储的是interceptorMapping列表(它包括一个Interceptor和一个name),所有的截拦器必须实现Interceptor的intercept方法,而该方法的参数恰恰又是ActionInvocation,在intercept方法中还是调用invocation.invoke(),从而实现了一个Interceptor链的调用。当所有的Interceptor执行完,最后调用invokeActionOnly方法来执行Action相应的方法。
protected
String invokeAction(Object action, ActionConfig actionConfig)
throws
Exception {
String methodName
=
proxy.getMethod();
String timerKey
=
"
invokeAction:
"
+
proxy.getActionName();
try
{
UtilTimerStack.push(timerKey);
boolean
methodCalled
=
false
;
Object methodResult
=
null
;
Method method
=
null
;
try
{
//
获得需要执行的方法
method
=
getAction().getClass().getMethod(methodName,
new
Class[
0
]);
}
catch
(NoSuchMethodException e) {
//
如果没有对应的方法,则使用do+Xxxx来再次获得方法
try
{
String altMethodName
=
"
do
"
+
methodName.substring(
0
,
1
).toUpperCase()
+
methodName.substring(
1
);
method
=
getAction().getClass().getMethod(altMethodName,
new
Class[
0
]);
}
catch
(NoSuchMethodException e1) {
//
well, give the unknown handler a shot
if
(unknownHandler
!=
null
) {
try
{
methodResult
=
unknownHandler.handleUnknownActionMethod(action, methodName);
methodCalled
=
true
;
}
catch
(NoSuchMethodException e2) {
//
throw the original one
throw
e;
}
}
else
{
throw
e;
}
}
}
if
(
!
methodCalled) {
methodResult
=
method.invoke(action,
new
Object[
0
]);
}
//
根据不同的Result类型返回不同值
//
如输出流Result
if
(methodResult
instanceof
Result) {
this
.explicitResult
=
(Result) methodResult;
return
null
;
}
else
{
return
(String) methodResult;
}
}
catch
(NoSuchMethodException e) {
throw
new
IllegalArgumentException(
"
The
"
+
methodName
+
"
() is not defined in action
"
+
getAction().getClass()
+
""
);
}
catch
(InvocationTargetException e) {
//
We try to return the source exception.
Throwable t
=
e.getTargetException();
if
(actionEventListener
!=
null
) {
String result
=
actionEventListener.handleException(t, getStack());
if
(result
!=
null
) {
return
result;
}
}
if
(t
instanceof
Exception) {
throw
(Exception) t;
}
else
{
throw
e;
}
}
finally
{
UtilTimerStack.pop(timerKey);
}
}
好了,action执行完了,还要根据ResultConfig返回到view,也就是在invoke方法中调用executeResult方法。
private
void
executeResult()
throws
Exception {
//
根据ResultConfig创建Result
result
=
createResult();
String timerKey
=
"
executeResult:
"
+
getResultCode();
try
{
UtilTimerStack.push(timerKey);
if
(result
!=
null
) {
//
这儿正式执行:)
//
可以参考Result的实现,如用了比较多的ServletDispatcherResult,ServletActionRedirectResult,ServletRedirectResult
result.execute(
this
);
}
else
if
(resultCode
!=
null
&&
!
Action.NONE.equals(resultCode)) {
throw
new
ConfigurationException(
"
No result defined for action
"
+
getAction().getClass().getName()
+
"
and result
"
+
getResultCode(), proxy.getConfig());
}
else
{
if
(LOG.isDebugEnabled()) {
LOG.debug(
"
No result returned for action
"
+
getAction().getClass().getName()
+
"
at
"
+
proxy.getConfig().getLocation());
}
}
}
finally
{
UtilTimerStack.pop(timerKey);
}
}
public
Result createResult()
throws
Exception {
if
(explicitResult
!=
null
) {
Result ret
=
explicitResult;
explicitResult
=
null
;;
return
ret;
}
ActionConfig config
=
proxy.getConfig();
Map results
=
config.getResults();
ResultConfig resultConfig
=
null
;
synchronized
(config) {
try
{
//
根据result名称获得ResultConfig,resultCode就是result的name
resultConfig
=
(ResultConfig) results.get(resultCode);
}
catch
(NullPointerException e) {
}
if
(resultConfig
==
null
) {
//
如果找不到对应name的ResultConfig,则使用name为*的Result
resultConfig
=
(ResultConfig) results.get(
"
*
"
);
}
}
if
(resultConfig
!=
null
) {
try
{
//
参照StrutsObjectFactory的代码
Result result
=
objectFactory.buildResult(resultConfig, invocationContext.getContextMap());
return
result;
}
catch
(Exception e) {
LOG.error(
"
There was an exception while instantiating the result of type
"
+
resultConfig.getClassName(), e);
throw
new
XWorkException(e, resultConfig);
}
}
else
if
(resultCode
!=
null
&&
!
Action.NONE.equals(resultCode)
&&
unknownHandler
!=
null
) {
return
unknownHandler.handleUnknownResult(invocationContext, proxy.getActionName(), proxy.getConfig(), resultCode);
}
return
null
;
}
//
StrutsObjectFactory
public
Result buildResult(ResultConfig resultConfig, Map extraContext)
throws
Exception {
String resultClassName
=
resultConfig.getClassName();
if
(resultClassName
==
null
)
return
null
;
//
创建Result,因为Result是有状态的,所以每次请求都新建一个
Object result
=
buildBean(resultClassName, extraContext);
//
这句很重要,后面将会谈到,reflectionProvider参见OgnlReflectionProvider;
//
resultConfig.getParams()就是result配置文件里所配置的参数<param></param>
//
setProperties方法最终调用的是Ognl类的setValue方法
//
这句其实就是把param名值设置到根对象result上
reflectionProvider.setProperties(resultConfig.getParams(), result, extraContext);
if
(result
instanceof
Result)
return
(Result) result;
throw
new
ConfigurationException(result.getClass().getName()
+
"
does not implement Result.
"
);
}
public
class
TestOgnl {
private
User user;
private
Map context;
@Before
public
void
setUp()
throws
Exception {
}
@Test
public
void
ognlGetValue()
throws
Exception {
reset();
Assert.assertEquals(
"
myyate
"
, Ognl.getValue(
"
name
"
, user));
Assert.assertEquals(
"
cares
"
, Ognl.getValue(
"
dept.name
"
, user));
Assert.assertEquals(
"
myyate
"
, Ognl.getValue(
"
name
"
, context, user));
Assert.assertEquals(
"
contextmap
"
, Ognl.getValue(
"
#name
"
, context, user));
Assert.assertEquals(
"
parker
"
, Ognl.getValue(
"
#pen
"
, context, user));
}
@Test
public
void
ognlSetValue()
throws
Exception {
reset();
Ognl.setValue(
"
name
"
, user,
"
myyateC
"
);
Assert.assertEquals(
"
myyateC
"
, Ognl.getValue(
"
name
"
, user));
Ognl.setValue(
"
dept.name
"
, user,
"
caresC
"
);
Assert.assertEquals(
"
caresC
"
, Ognl.getValue(
"
dept.name
"
, user));
Assert.assertEquals(
"
contextmap
"
, Ognl.getValue(
"
#name
"
, context, user));
Ognl.setValue(
"
#name
"
, context, user,
"
contextmapC
"
);
Assert.assertEquals(
"
contextmapC
"
, Ognl.getValue(
"
#name
"
, context, user));
Assert.assertEquals(
"
parker
"
, Ognl.getValue(
"
#pen
"
, context, user));
Ognl.setValue(
"
#name
"
, context, user,
"
parkerC
"
);
Assert.assertEquals(
"
parkerC
"
, Ognl.getValue(
"
#name
"
, context, user));
}
public
static
void
main(String[] args)
throws
Exception {
JUnitCore.runClasses(TestOgnl.
class
);
}
private
void
reset() {
user
=
new
User(
"
myyate
"
,
new
Dept(
"
cares
"
));
context
=
new
OgnlContext();
context.put(
"
pen
"
,
"
parker
"
);
context.put(
"
name
"
,
"
contextmap
"
);
}
}
class
User {
public
User(String name, Dept dept) {
this
.name
=
name;
this
.dept
=
dept;
}
String name;
private
Dept dept;
public
Dept getDept() {
return
dept;
}
public
String getName() {
return
name;
}
public
void
setDept(Dept dept) {
this
.dept
=
dept;
}
public
void
setName(String name) {
this
.name
=
name;
}
}
class
Dept {
public
Dept(String name) {
this
.name
=
name;
}
private
String name;
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name
=
name;
}
}
这样,一个Struts2的请求流程基本上就结束了。其实我觉得做项目把Struts2参考文档看两遍就可以了,