在访问RxJava线程

时间:2017-11-21 21:30:52

标签: multithreading spring-mvc rx-java

我在尝试访问rxjava Schedulers.io()的线程中的Spring会话范围bean时遇到异常

Caused by: 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.

这是我的scoped bean

@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
@Getter
@Setter
public class SearchSession {
    List<String> results;
}

我的控制器

@Controller
@AllArgsConstructor(onConstructor=@__(@Autowired))
@Slf4j
public class SearchController {
    private SearchService searchService;
    private SearchSession searchSession;

    @GetMapping("/search")
    public DeferredResult<ModelAndView> getResults() {
        DeferredResult<ModelAndView> deferredResult = new DeferredResult<>();

        searchService.search("param1", "param2")
          .map(results -> {
              searchSession.setResults(results);
              return results;
          )
          .subscribeOn(Schedulers.io())
          .subscribe(
              results -> {
                  ModelAndView view = new ModelAndView("search");
                  view.addObject("results", results);
                  deferredResult.setResult(view);
          );
        return deferredResult;
    }
}

我尝试定义一个扩展RequestContextListener的类,并在调用RequestContextHolder.setRequestAttributes时将参数inheritable设置为true,以允许最初处理请求的线程与RxJava线程之间的继承,但它不起作用。

public class InheritableRequestContextListener extends RequestContextListener {
private static final String REQUEST_ATTRIBUTES_ATTRIBUTE =
    InheritableRequestContextListener.class.getName() + ".REQUEST_ATTRIBUTES";

    @Override
    public void requestInitialized(ServletRequestEvent requestEvent) {
        if (!(requestEvent.getServletRequest() instanceof HttpServletRequest)) {
            throw new IllegalArgumentException(
                "Request is not an HttpServletRequest: " + requestEvent.getServletRequest());
        }
        HttpServletRequest request = (HttpServletRequest) requestEvent.getServletRequest();
        ServletRequestAttributes attributes = new ServletRequestAttributes(request);
        request.setAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE, attributes);
        LocaleContextHolder.setLocale(request.getLocale());
        RequestContextHolder.setRequestAttributes(attributes, true);
    }
}

我还尝试创建一个由Spring管理的自定义RxJava调度程序,但它不起作用。

@Bean
public Scheduler scheduler() {
    final ThreadFactory threadFactory = new ThreadFactoryBuilder()
            .setNameFormat("SearchThread-%d")
            .setDaemon(true)
            .build();
    return Schedulers.from(Executors.newFixedThreadPool(10, threadFactory));
}

您是否知道如何在RxJava线程中访问我的Spring会话范围bean?

0 个答案:

没有答案