大致把源码中类前面的一段注释给翻译一下:
    
     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)
public BackgroundProcess(String threadName, final ActionInvocation invocation, int threadPriority)  {
{
 this.invocation = invocation;
        this.invocation = invocation;
 this.action = invocation.getAction();
        this.action = invocation.getAction();

 try
        try  {
{

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

 public void run()
                public void run()  {
{

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

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

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

 } catch (Exception e)
        } catch (Exception e)  {
{
 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