Spring Controller在响应发送后开始处理

mre*_*rer 10 java concurrency spring-mvc

我正在使用Spring MVC控制器,并希望开始执行一个新线程的任务.但是线程不应该立即启动,而是仅在响应发送到客户端之后.

手段 - 按严格的时间顺序:

  1. 请求
  2. 返回新的ResponseEntity .../client接收Http状态200 ok.
  3. 任务的处理开始.

我如何实现这一目标?

我想使用Spring的异步抽象,调用带有@Async注释的方法,但这种方式我都不能保证新的线程等待发送的响应.

Ser*_*sta 12

你可以使用拦截器.在Spring MVC中处理请求的顺序是:

  • DispatcherServlet获取请求,响应对并确定处理
  • [可选]拦截器preHandle被调用(带有停止处理的选项)
  • 控制器被调用
  • [可选]拦截器postHandle被调用
  • ViewResolver和view执行实际的Response处理并发送响应
  • 调用[可选] interperors afterCompletion

上面的内容已经过度简化,目的只是为了表明在将响应发送给客户端之后调用拦截器afterCompletion方法,并具有以下签名:

void afterCompletion(HttpServletRequest request,
                     HttpServletResponse response,
                     Object handler,
                     Exception ex)
                     throws Exception
Run Code Online (Sandbox Code Playgroud)

在该方法中,您可以afterCompletion在开始处理之前测试异常的发生和响应()的正确性.

  • 拦截器的 afterCompletion() 甚至在发送响应之前就正在执行。我是否缺少一些明显的东西? (2认同)

Ita*_*tto 6

HandlerInterceptor就是解决方案,但代码比预期的要复杂一些。

下面是一个代码建议,通过将整个解决方案放在一个类中来使其更简单:

private static final ThreadLocal<Object> result = new ThreadLocal<Object>();

@RequestMapping("/mypath")
public Object execute() throws Exception {
    Object obj = new Object();
    result.set(obj); // Save the object to be used after response
    return obj;
}

@Bean
public MappedInterceptor interceptor() {
    return new MappedInterceptor(Arrays.array("/mypath"), new HandlerInterceptor() {
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            // Get the saved object
            Object results = result.get();

            // Clean for the next request
            result.set(null);

            // TODO Your code to be executed after response.
        }
    });
}
Run Code Online (Sandbox Code Playgroud)


Hil*_*lle 5

如果"在响应发送后"要求通过"在呈现视图之后"满足,则可以使用HandlerInterceptor的实现.举个例子比较 Spring 3 MVC拦截器教程的例子,触发你的工作afterCompletion.

如果你的工作需要在"击中电线后"触发,我想知道原因.