2017-10-18 17 views
0

struts 웹 응용 프로그램에서 긴 폴링을 수행하려고합니다. ActionSupport 액션 메소드 내에서 AsyncContext를 시작하고 시간이 많이 걸리는 비동기 작업을 한 다음 스트럿츠에 SUCCESS 응답을 보내려합니다.Struts가 AsyncContext에서 응답을 보냅니다.

PrintWriter pw = asyncContext.getResponse().getWriter();을 작성하고 원시 응답을 작성할 수 있지만 struts.xml의 미리 정의 된 결과를 처리하기 위해 struts에 신호를 보내고 싶습니다. 이것이 가능한가? 나는 단순히 SUCCESS 및 스트럿을 반환 할 수 있습니다 비 비동기 작업에서

<action name="myAction" method="action1" class="myActionClass"> 
    <result name="success" type="redirectAction"> 
     /pages/myPage.jsp  <!-- I want to run this from async ---> 
    </result> 
</action> 

는 모든 것을 처리한다,하지만 난 비동기 동작과 유사한 효과를 달성에 문제가 발생하고있다. 이것은 내가 지금까지 가지고있는 것입니다 :

public void action1() { 
    HttpServletRequest req = ServletActionContext.getRequest(); 
    HttpServletResponse res = ServletActionContext.getResponse(); 

    final AsyncContext asyncContext = req.startAsync(req, res); 

    asyncContext.start(new Runnable() { 
     public void run() { 
      // Some time-consuming polling task is done here 

      asyncContext.complete(); 

      // Can I somehow proceed to predefined struts result from here? 
     } 
    }); 
} 
+0

'execAndWait' 인터셉터가 있습니다 - http://struts.apache.org/core-developers/execute-and-wait-interceptor.html. –

답변

0

현재 명확하게 할 수없는 것 같습니다. 이 지원을 Struts로 가져올 수 있다면 일하고 있는데, 현재는 작동하는 해킹이 있습니다. 나는 아래 StrutsExecuteFilter 확장 :

package me.zamani.yasser.ww_convention.utils; 

import org.apache.struts2.dispatcher.PrepareOperations; 
import org.apache.struts2.dispatcher.filter.StrutsExecuteFilter; 
import org.apache.struts2.dispatcher.filter.StrutsPrepareFilter; 
import org.apache.struts2.dispatcher.mapper.ActionMapping; 

import javax.servlet.*; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import java.io.IOException; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.ThreadFactory; 

/** 
* Created by user on 8/31/2017. 
*/ 
public class MYStrutsAsyncExecuteFilter extends StrutsExecuteFilter { 
    public final int REQUEST_TIMEOUT = 240000;//set your desired timeout here 
    private ExecutorService exe; 

    @Override 
    public void init(FilterConfig filterConfig) throws ServletException { 
     int size = 41;//set your desired pool size here 
     exe = Executors.newFixedThreadPool(
       size, 
       new ThreadFactory() { 
        public Thread newThread(Runnable r) { 
         return new Thread(r, "My Struts Async Processor"); 
        } 
       } 
     ); 

     super.init(filterConfig); 
    } 

    @Override 
    public void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain) throws IOException, ServletException { 

     final HttpServletRequest request = (HttpServletRequest) req; 
     final HttpServletResponse response = (HttpServletResponse) res; 

     if (excludeUrl(request)) { 
      chain.doFilter(request, response); 
      return; 
     } 

     // This is necessary since we need the dispatcher instance, which was created by the prepare filter 
     if (execute == null) { 
      lazyInit(); 
     } 

     final ActionMapping mapping = prepare.findActionMapping(request, response); 

     //if recursion counter is > 1, it means we are in a "forward", in that case a mapping will still be 
     //in the request, if we handle it, it will lead to an infinite loop, see WW-3077 
     final Integer recursionCounter = (Integer) request.getAttribute(PrepareOperations.CLEANUP_RECURSION_COUNTER); 

     if (mapping == null || recursionCounter > 1) { 
      boolean handled = execute.executeStaticResourceRequest(request, response); 
      if (!handled) { 
       chain.doFilter(request, response); 
      } 
     } else { 
      /* I ADDED THESE */ 
      final AsyncContext context = req.startAsync(); 
      context.setTimeout(REQUEST_TIMEOUT); 

      context.addListener(new AsyncListener() { 
       public void onComplete(AsyncEvent asyncEvent) throws IOException { 
       } 

       public void onTimeout(AsyncEvent asyncEvent) throws IOException { 
        context 
          .getResponse() 
          .getWriter().write("Request Timeout"); 
       } 

       public void onError(AsyncEvent asyncEvent) throws IOException { 
        context 
          .getResponse() 
          .getWriter().write("Processing Error"); 
       } 

       public void onStartAsync(AsyncEvent asyncEvent) throws IOException { 
       } 
      }); 
      exe.execute(new ContextExecution(context, mapping)); 
     } 
    } 

    private boolean excludeUrl(HttpServletRequest request) { 
     return request.getAttribute(StrutsPrepareFilter.class.getName() + ".REQUEST_EXCLUDED_FROM_ACTION_MAPPING") != null; 
    } 

    @Override 
    public void destroy() { 
     exe.shutdown(); 
     super.destroy(); 
    } 

    class ContextExecution implements Runnable { 

     final AsyncContext context; 
     ActionMapping mapping; 

     public ContextExecution(AsyncContext context, ActionMapping mapping) { 
      this.context = context; 
      this.mapping=mapping; 
     } 

     public void run() { 
      try { 
       execute.executeAction((HttpServletRequest) context.getRequest(), 
         (HttpServletResponse) context.getResponse(), mapping); 

       context.complete(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

다음

<filter> 
    <filter-name>struts2asyncexecute</filter-name> 
    <filter-class>me.zamani.yasser.ww_convention.utils.MYStrutsAsyncExecuteFilter</filter-class> 
    <async-supported>true</async-supported> 
</filter> 

후 특정 패키지에 원하는 비동기 작업을 넣어 스트럿의 원래 필터에서 제외하지만 web.xml에 위의 필터에 매핑.

더 많은 구성 가능하고 명확한 다음 Struts로 가져 오기 위해 개선하기 위해 노력하고 있습니다.

앱에서 테스트 해 주시겠습니까? 저에게 어떤 생각인지 알려 주시기 바랍니다.