2017-03-01 92 views
4

我遇到了一个问题,即在方法返回CompletionStage时,我的筛选器运行了两次。从RequestMappinghere)的文档,它是一个支持的返回值。Spring Boot为请求返回CompletionStage运行两次筛选器

一个CompletionStage(例如由CompletableFuture实现),应用程序用它来在自己选择的单独线程中产生返回值,作为返回Callable的替代方法。

由于项目很复杂,并发代码很多,我创建了一个新的简单的spring-boot项目。这是它的(唯一的)控制器:

@Controller 
public class BaseController { 
    @RequestMapping("/hello") 
    @ResponseBody 
    public CompletionStage<String> world() { 
     return CompletableFuture.supplyAsync(() -> "Hello World"); 
    } 
} 

和过滤器:

@WebFilter 
@Component 
public class GenericLoggingFilter extends GenericFilterBean { 
    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, 
         FilterChain chain) throws IOException, ServletException { 
     HttpServletRequest httpServletRequest = (HttpServletRequest) request; 

     System.out.println(httpServletRequest.getMethod() + " " + 
          httpServletRequest.getRequestURI()); 

     chain.doFilter(request, response); 
    } 
} 

当我拨打电话curl http://localhost:8080/hello,它打印GET /hello两次在控制台上。当我改变控制器方法返回一个String

@RequestMapping("/hello") 
@ResponseBody 
public String world() { 
    return "Hello World"; 
} 

它只打印一次。即使我将其更改为Callable,但没有真正的并发意义(当然,弹簧本身可能将其视为Async请求)。

所以,如果弹簧再次运行整个网络栈有一个请求上下文中可用,甚至没有什么意义,因为以下几点:

@RequestMapping("/hello") 
@ResponseBody 
public CompletionStage<String> world() { 
    return CompletableFuture.supplyAsync(() -> { 
     System.out.println(RequestContextHolder.currentRequestAttributes()); 
     return "Hello World"; 
    }); 
} 

抛出异常:IllegalStateException: No thread-bound request found...

令人惊讶的是,下列工作:

@RequestMapping("/hello") 
@ResponseBody 
public Callable<String> world() { 
    return() -> { 
     System.out.println(RequestContextHolder.currentRequestAttributes()); 
     return "Hello World"; 
    }; 
} 

所以,我不确定不少东西。

  1. 看来,CallableCompletionStage在上下文中区别对待哪个线程的它在执行。
  2. 如果是这样的话,那么为什么我的过滤器在每种情况下运行两次?如果筛选器的工作是设置某个特定于请求的上下文,那么如果无法访问它,则再次运行该筛选器对于CompletionStage没有意义。
  3. 为什么过滤器会以两种方式运行两次?

回答

2

请用OncePerRequestFilter替换GenericFilterBean