将DeferredResult和Spring AsyncRestTemplate中的线程关联到Shiro

将DeferredResult和Spring AsyncRestTemplate中的线程关联到Shiro,spring,rest,spring-mvc,asynchronous,shiro,Spring,Rest,Spring Mvc,Asynchronous,Shiro,如何通过Subject.associateWith(work)将Spring延迟结果产生的线程与ApacheShiro主题相关联 对于可调用或可运行的对象,这是很清楚的,但对于异步Spring对象,这是不清楚的 @RequestMapping(value = "etc/async/{atbId}", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE }) @ResponseBody

如何通过Subject.associateWith(work)将Spring延迟结果产生的线程与ApacheShiro主题相关联

对于可调用或可运行的对象,这是很清楚的,但对于异步Spring对象,这是不清楚的

   @RequestMapping(value = "etc/async/{atbId}", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
    @ResponseBody
    public DeferredResult<ResponseEntity<String>> getEtcById(HttpServletResponse response,
                               @PathVariable("atbId") long atbId,                               
                               HttpSession session) throws IOException {

        log.debug("Enter async getEtcById with ListenableFuture");
        final String userName = (String) session.getAttribute(SessionKeys.USER_ID);
        final AuthenticatedAsyncRestTemplate restTemplate = new AuthenticatedAsyncRestTemplate();

        final DeferredResult<ResponseEntity<String>> result = new DeferredResult<>(100000); 
        ListenableFuture<ResponseEntity<String>> future = 
                restTemplate.getForEntity("http://localhost:8079/ts.download/download/etc/{atbId}?userName={userName}", String.class, atbId, userName);  

        future.addCallback(  
                  new ListenableFutureCallback<ResponseEntity<String>>() {  
                    @Override  
                    public void onSuccess(ResponseEntity<String> response) {  
                        // Will be called in HttpClient thread  
                        log.debug("ListenableFuture onSuccess: " + response.getBody());                         
                        result.setResult(response);  
                    }  

                    @Override  
                    public void onFailure(Throwable t) {  
                        log.error("ListenableFuture onFailure", t);  
                        result.setErrorResult(t.getMessage());  
                    }  
                });  

        log.debug("Leaving async getEtcById");
        return result;
    }
@RequestMapping(value=“etc/async/{atbId}”,method=RequestMethod.GET,products={MediaType.APPLICATION\u JSON\u value})
@应答器
公共延迟结果getEtcById(HttpServletResponse响应,
@路径变量(“atbId”)长atbId,
HttpSession(会话)引发IOException{
debug(“使用ListenableFuture输入异步getEtcById”);
最终字符串用户名=(字符串)session.getAttribute(SessionKeys.USER\u ID);
最终AuthenticatedAsyncRestTemplate restTemplate=新AuthenticatedAsyncRestTemplate();
最终延期结果=新延期结果(100000);
可列出的未来=
restTemplate.getForEntity(“http://localhost:8079/ts.download/download/etc/{atbId}?用户名={userName}”,String.class,atbId,userName);
future.addCallback(
新建ListenableFutureCallback(){
@凌驾
成功时公共无效(响应性响应){
//将在HttpClient线程中调用
debug(“ListenableFuture onSuccess:+response.getBody());
result.setResult(响应);
}  
@凌驾
失效时的公共无效(可丢弃的t){
log.error(“ListenableFuture onFailure”,t);
result.setErrorResult(t.getMessage());
}  
});  
debug(“离开异步getEtcById”);
返回结果;
}
rest调用正常,但我收到以下错误消息:

Servlet[spring]在具有路径的上下文中的Servlet.service() [/mycontext]引发异常[java.lang.RuntimeException: org.apache.shiro.unavailableSecurityManager异常:否 调用代码可访问的SecurityManager,绑定到 org.apache.shiro.util.ThreadContext或作为vm静态单例 是无效的应用程序配置。]具有根本原因 org.apache.shiro.unavailableSecurityManager异常:否 调用代码可访问的SecurityManager,绑定到 org.apache.shiro.util.ThreadContext或作为vm静态单例。这 是无效的应用程序配置。在 org.apache.shiro.SecurityUtils.getSecurityManager(SecurityUtils.java:123) 位于org.apache.shiro.subject.subject$Builder。(subject.java:627) 位于org.apache.shiro.SecurityUtils.getSubject(SecurityUtils.java:56) 在 org.apache.shiro.web.servlet.ShiroHttpServletRequest.getSubject(ShiroHttpServletRequest.java:88) 在 org.apache.shiro.web.servlet.ShiroHttpServletRequest.getSubjectPrincipal(ShiroHttpServletRequest.java:93) 在 org.apache.shiro.web.servlet.ShiroHttpServletRequest.getUserPrincipal(ShiroHttpServletRequest.java:111) 在 org.springframework.web.servlet.FrameworkServlet.getUsernameForRequest(FrameworkServlet.java:1079) 在 org.springframework.web.servlet.FrameworkServlet.PublishRequestHandleEvent(FrameworkServlet.java:1065) 在 org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:996) 在 org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852) 位于javax.servlet.http.HttpServlet.service(HttpServlet.java:621) org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837) 位于javax.servlet.http.HttpServlet.service(HttpServlet.java:728) org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 在 org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:749) 在 org.apache.catalina.core.ApplicationDispatcher.doDispatch(ApplicationDispatcher.java:660) 在 org.apache.catalina.core.ApplicationDispatcher.dispatcher(ApplicationDispatcher.java:626) 在 org.apache.catalina.core.AsyncContextImpl$1.run(AsyncContextImpl.java:225) 在 org.apache.catalina.core.AsyncContextImpl.doInternalDispatch(AsyncContextImpl.java:368) 在 org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:217) 在 org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) 在 org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) 在 org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100) 在 org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953) 在 org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) 在 org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:300) 在 org.apache.coyote.http11.AbstractHttp11Processor.asyncDispatch(AbstractHttp11Processor.java:1636) 在 org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:599) 在 org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1721) 在 org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1679) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 运行(Thread.java:724)

我认为这有助于: