大致把源碼中類前面的一段注釋給翻譯一下:
1 ExecuteAndWaitInterceptor很適合在后臺長時間運行的action時,他可以可為用戶一個友好的等待界面,例如進度條。
2 不在默認的攔截stack 里面,使用的時候需要配置,但必須是在攔截堆棧的最后一個。
大致配置如下:
<action name="test" method="test" class="com.joe.web.action.ActionTest">
<interceptor-ref name="completeStack"/>
<interceptor-ref name="execAndWait">
<param name="delay">1000</param>
<param name="delaySleepInterval">50</param>
</interceptor-ref>
<result name="wait">wait.jsp</result>
<result name="success">success.jsp</result>
</action> 3 使用的時候需要配置一個名為wait的result,并指向自己的等待頁面,如果沒有struts
將使用FreeMarker代替,通過使用FreemarkerResult動態注入一個等待頁面:struts提供的面板頁面可見于:
org/apache/struts2/interceptor/wait.ftl
內容大致如下:
<html>
<head>
<meta http-equiv="refresh" content="5;url=<@s.url includeParams="none"/>"/>
</head>
<body>
Please wait while we process your request...
<p/>
This page will reload automatically and display your request when it is completed.
</body>
</html>
其中的includeParams參數取值為
none,不把參數參加到url參數中
all,是把get和post中的參數參加到url參數中
get,是只把get中的參數參加到url參數中
execAndWait攔截器有2個參數:
delay :意思是初始等待多少秒才出現等待頁面。當在這個等待時間內action執行完畢,就不用出現wai界面,如果不配,一開始就會出現。
delaySleepInterval:每個對少時間檢查action是否執行完畢。
-------------
大致的原理是:strus遇到這種配置了execAndWait的action會另外起一個線程來執行,這個線程名叫BackgroundProcess,并通過一個done屬性的變化來標準執行情況,struts將此線程放到session中,頁面每隔一段時間去檢查是done==true? 如果不是,就據需返回wai頁面,否則返回主action的返回界面。
BackgroundProcess大致源碼:

public BackgroundProcess(String threadName, final ActionInvocation invocation, int threadPriority)
{
this.invocation = invocation;
this.action = invocation.getAction();

try
{

final Thread t = new Thread(new Runnable()
{

public void run()
{

try
{
beforeInvocation();
result = invocation.invokeActionOnly();
afterInvocation();

} catch (Exception e)
{
exception = e;
}

done = true;
}
});
t.setName(threadName);
t.setPriority(threadPriority);
t.start();

} catch (Exception e)
{
exception = e;
}
}
當這個action結束后會將done屬性設置為true表示執行結束,正是每次去檢查這個屬性來判別。
攔截器主要源碼:
if ((!executeAfterValidationPass || secondTime) && bp == null) {
bp = getNewBackgroundProcess(name, actionInvocation, threadPriority);
session.put(KEY + name, bp);//放入session
performInitialDelay(bp); // first time let some time pass before showing wait page
secondTime = false;
}
if ((!executeAfterValidationPass || !secondTime) && bp != null && !bp.isDone()) {//是否完畢
actionInvocation.getStack().push(bp.getAction());//將后臺action的相關信息push到statck,時候的頁面可是使用
if (TokenHelper.getToken() != null) {
session.put(TokenHelper.getTokenName(), TokenHelper.getToken());
}
Map results = proxy.getConfig().getResults();
if (!results.containsKey(WAIT)) {//如果沒有配置wait,struts將為你inject一個
LOG.warn("ExecuteAndWait interceptor has detected that no result named 'wait' is available. " +
"Defaulting to a plain built-in wait page. It is highly recommend you " +
"provide an action-specific or global result named '" + WAIT +
"'.");
// no wait result? hmm -- let's try to do dynamically put it in for you!
//we used to add a fake "wait" result here, since the configuration is unmodifiable, that is no longer
//an option, see WW-3068
FreemarkerResult waitResult = new FreemarkerResult();
container.inject(waitResult);
waitResult.setLocation("/org/apache/struts2/interceptor/wait.ftl");
waitResult.execute(actionInvocation);
return Action.NONE;
}
return WAIT;
} else if ((!executeAfterValidationPass || !secondTime) && bp != null && bp.isDone()) {//如果執行完畢return bp.getResult();
session.remove(KEY + name);
actionInvocation.getStack().push(bp.getAction());
// if an exception occured during action execution, throw it here
if (bp.getException() != null) {
throw bp.getException();
}
return bp.getResult();
} else {
// this is the first instance of the interceptor and there is no existing action
// already run in the background, so let's just let this pass through. We assume
// the action invocation will be run in the background on the subsequent pass through
// this interceptor
return actionInvocation.invoke();
}
。
一個簡單的例子(不包含lib):
/Files/freeman1984/execAndWait.rar