将DeferredResult和Spring AsyncRestTemplate中的线程关联到Shiro
如何通过Subject.associateWith(work)将Spring延迟结果产生的线程与ApacheShiro主题相关联 对于可调用或可运行的对象,这是很清楚的,但对于异步Spring对象,这是不清楚的将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
@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)
我认为这有助于: