Spring MVC 中的 TaskExecutor 不是异步的

TaskExecutor in Spring MVC is not asynchronous

工作管理器在管理控制台中定义,池大小最小为 1 和 5。该 Web 应用具有以下配置。

Web.xml

<web-app id="RestController" metadata-complete="true" version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <servlet>
        <servlet-name>rest-controller</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>rest-controller</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

申请-Context.xml

`<!-- Empty. I moved all the servlet related entities from here -->`

rest-Controller-servlet.xml

 <context:component-scan base-package="com.package.main-pack" />    
 <task:annotation-driven executor="taskExecutor"/>  
 <mvc:annotation-driven />  
 <task:executor id="taskExecutor" pool-size="5" /> 

RestController.java

@RequestMapping(value = "/reportFake", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@Override
public List<String> searchFake() {
    List<String> stringArr = new ArrayList<String>();
    for (String folder : foldername) {
        Future<String> result = reportLookup.doParallelFake(folder);
        try {
            while (true) {
                if (result.isDone()) {
                    stringArr.add(result.get());
                    Logger.debug(RestController.class,
                            "Executed and Returned");
                    break;
                }
            }
        } catch (InterruptedException e) {
            Logger.error(RestController.class, e.getMessage());
        } catch (ExecutionException e) {
            Logger.error(RestController.class, e.getMessage());
        }
    }
    return stringArr;
}

ReportLookupExecutor.java

@Service("reportLookup")
public class ReportLookupExecutor implements ReportLookupIntf {

@Async("taskExecutor")
@Async("taskExecutor")
@Override
public Future<String> doParallelFake(String folder) {
    logger.debug("Execute method asynchronously - "
            + Thread.currentThread().getName());

    try {
        Thread.sleep(5000);
        return new AsyncResult<String>("Folder Name :: " + folder);
    } catch (InterruptedException e) {
        logger.error(e);
    }
    return null;
}

输出

[11/4/15 12:41:24:349 EST] 0000014d SystemOut     O [DEBUG] 04 Nov 12:41:24 PM taskExecutor-1  Execute method asynchronously - taskExecutor-1
[11/4/15 12:41:29:365 EST] 0000007b SystemOut     O [DEBUG] 04 Nov 12:41:29 PM WebContainer : 3  Executed and Returned
[11/4/15 12:41:29:366 EST] 0000014e SystemOut     O [DEBUG] 04 Nov 12:41:29 PM taskExecutor-2  Execute method asynchronously - taskExecutor-2
[11/4/15 12:41:34:365 EST] 0000007b SystemOut     O [DEBUG] 04 Nov 12:41:34 PM WebContainer : 3  Executed and Returned

现在,我尝试关注this link。 我手动抛出一个异常来检查堆栈跟踪,发现它被 ibm.asynchbeans 运行 并被 Spring 适当拦截。这是堆栈跟踪中的一个片段。

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:611)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.interceptor.AsyncExecutionInterceptor.call(AsyncExecutionInterceptor.java:97)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:314)
at java.util.concurrent.FutureTask.run(FutureTask.java:149)
at org.springframework.scheduling.commonj.DelegatingWork.run(DelegatingWork.java:61)
at com.ibm.ws.asynchbeans.J2EEContext.run(J2EEContext.java:1178)
at com.ibm.ws.asynchbeans.WorkWithExecutionContextImpl.go(WorkWithExecutionContextImpl.java:199)
at com.ibm.ws.asynchbeans.CJWorkItemImpl.run(CJWorkItemImpl.java:236)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1862)

非常感谢任何帮助。

好的!我终于能够做到 运行。解决方案是在获取 future 的第一个值之前对 async 方法进行所有调用。我能够通过创建一个未来对象列表来做到这一点。这就是最终调用 class 的样子。

RestController.java

@RequestMapping(value = "/reportFake", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@Override
public List<String> searchFake() throws InterruptedException,
        ExecutionException {
    List<Future<String>> futureArr = new ArrayList<Future<String>>();
    for (String folder : new String[] { "One", "Two", "Three", "Four" }) {
        futureArr.add(reportLookup.doParallelFake(folder));
    }
    List<String> stringArr = new ArrayList<String>();
    for (Future<String> future : futureArr) {
        stringArr.add(future.get());
    }
    return stringArr;
}