本文介绍了将数据保存到会话时,Spring Async函数异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到有关HttpSession的 @Async 任务的问题.我想以异步方法将数据保存在会话中.发生的情况是正确返回了响应,但是在会话中保存数据时出现错误.请帮忙.

I am facing an issue regarding @Async task with HttpSession. I want to save the data in session in an async method. What happens is the response is returned correctly but I get an error while saving data in session. Please help.

我的控制器文件:

@RequestScope
@Controller
public class SomeController {

    @Autowired
    private ISomeService iSomeService;

    @ResponseBody
    @GetMapping("/some-func")
    public String someFunc() {
        iSomeService.myAsyncFunction("hello");
        return "ok";
    }
}

我的服务文件:

@RequestScope
@Service
public class SomeServiceImpl implements ISomeService {

    @Autowired
    private HttpSession session;

    @Async("threadPoolTaskExecutor")
    @Override
    public void myAsyncFunction(String s) {

        session.setAttribute("key", s);
    }
}

我的配置文件:

@EnableAsync
@Configuration
public class ThreadConfig {

    @Bean(name = "threadPoolTaskExecutor")
    public Executor threadPoolTaskExecutor() {
        return new ThreadPoolTaskExecutor();
    }
}

我的Stacktrace:

My Stacktrace:

2019-03-07 17:23:16.065 ERROR 29179 --- [lTaskExecutor-1] .a.i.SimpleAsyncUncaughtExceptionHandler : Unexpected error occurred invoking async method: public void com.example.demo.SomeServiceImpl.myAsyncFunction(java.lang.String)

java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
    at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) ~[spring-web-4.3.22.RELEASE.jar:4.3.22.RELEASE]
    at org.springframework.web.context.support.WebApplicationContextUtils.currentRequestAttributes(WebApplicationContextUtils.java:309) ~[spring-web-4.3.22.RELEASE.jar:4.3.22.RELEASE]
    at org.springframework.web.context.support.WebApplicationContextUtils.access$400(WebApplicationContextUtils.java:64) ~[spring-web-4.3.22.RELEASE.jar:4.3.22.RELEASE]
    at org.springframework.web.context.support.WebApplicationContextUtils$SessionObjectFactory.getObject(WebApplicationContextUtils.java:366) ~[spring-web-4.3.22.RELEASE.jar:4.3.22.RELEASE]
    at org.springframework.web.context.support.WebApplicationContextUtils$SessionObjectFactory.getObject(WebApplicationContextUtils.java:361) ~[spring-web-4.3.22.RELEASE.jar:4.3.22.RELEASE]
    at org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler.invoke(AutowireUtils.java:307) ~[spring-beans-4.3.22.RELEASE.jar:4.3.22.RELEASE]
    at com.sun.proxy.$Proxy93.setAttribute(Unknown Source) ~[na:na]
    at com.example.demo.SomeServiceImpl.myAsyncFunction(SomeServiceImpl.java:21) ~[classes/:na]
    at com.example.demo.SomeServiceImpl$$FastClassBySpringCGLIB$$9dbf1607.invoke(<generated>) ~[classes/:na]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.3.22.RELEASE.jar:4.3.22.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:736) ~[spring-aop-4.3.22.RELEASE.jar:4.3.22.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.3.22.RELEASE.jar:4.3.22.RELEASE]
    at org.springframework.aop.interceptor.AsyncExecutionInterceptor$1.call(AsyncExecutionInterceptor.java:115) ~[spring-aop-4.3.22.RELEASE.jar:4.3.22.RELEASE]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_191]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_191]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_191]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_191]

推荐答案

在我的头上,如果我们有 @Async 批注,那么我认为返回类型应为 CompletableFuture 就像javascript中的承诺一样.
因此,通过将服务方法的返回类型从 void 更改为 CompletableFuture< Void> ,可以解决此问题.

On top of my head, If We have @Async annotations then I think return type should be of type CompletableFuture like a promise in javascript.
So by changing the return type to service method from void to CompletableFuture<Void> solves the problem.

所以我修改了如下代码:

So I modified the code as below:

@Async("threadPoolTaskExecutor")
@Override
public CompletableFuture<Void> myAsyncFunction(String s) {

    session.setAttribute("key", s);
    return new CompletableFuture<Void>();
}

//要在异步中获取会话对象//这是错误的代码,但请检查适用性

// To get session object in Async// This is bad code but check suitability

所以在这里,我从HttpRequest获取会话对象并将其传递给Service,您在service处添加参数并在控制器上检查这些参数.
不要在服务或控制器上自动连接会话对象.

So here I am getting session object from the HttpRequest and passing it to Service, You add parameters at service and check those parameters at the controller.
Do not autowire session object at service or controller.

@RequestScope
@Controller
public class SomeController {

@Autowired
private SomeServiceImpl iSomeService;

@ResponseBody
@GetMapping("/some-func")
public String someFunc(HttpServletRequest request) throws ExecutionException, InterruptedException {
    HttpSession session = request.getSession();
    CompletableFuture<HttpSession> completableFuture= iSomeService.myAsyncFunction(session, "hello");
    HttpSession session1=completableFuture.get();
    System.out.println(session1.getAttribute("key"));
    return "ok";
}
}

@RequestScope
@Service
public class SomeServiceImpl {

@Async("threadPoolTaskExecutor")
public CompletableFuture<HttpSession> myAsyncFunction(HttpSession session, String s) {
    session.setAttribute("key", s);
    return CompletableFuture.completedFuture(session);
}
}

这篇关于将数据保存到会话时,Spring Async函数异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 20:18