joe--专注java,开源,架构,项目管理

STANDING ON THE SHOULDERS OF GIANTS
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

浅析struts中的ExecuteAndWaitInterceptor,以及简单例子

Posted on 2010-09-25 00:59  @joe  阅读(919)  评论(1编辑  收藏  举报

  大致把源码中类前面的一段注释给翻译一下:
    
     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,是把getpost中的参数参加到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
  
  


   

@joe 2010-09-25 00:59 发表评论