如何在spring mvc中的动作之前发送响应

时间:2015-08-18 12:19:08

标签: java spring spring-mvc model-view-controller

假设我的弹簧控制器功能接收到大量数据。 我想返回200 OK,假设数据结构正确,之后我想要执行处理,这可能需要一段时间。

据我了解,发送响应的唯一方法是通过 return 命令。但我不想结束响应发送功能。

是否还有其他方法可以在功能中间向客户端发送响应?

创建一个新的线程运行是显而易见的,但其他语言(JS)可以让你更优雅地处理它。

@RequestMapping(value = Connectors.CONNECTOR_HEARTBEAT, method = RequestMethod.POST)
public ResponseEntity<String> doSomething(@RequestBody List<Message> messages) {
    HttpStatus code = (messages!=null && !messages.isEmpty()) ? HttpStatus.OK
            : HttpStatus.NOT_FOUND;
    return new ResponseEntity<String>(res, code);
   // how do I add code here??
}

5 个答案:

答案 0 :(得分:8)

您当然可以在发送回复后进行处理。更一般的方法是使用afterCompletion的{​​{1}}方法。通过构造,它将在响应发送到客户端后执行,但它会强制您在控制器中之前部分中的2个组件中拆分逻辑,之后的部分在拦截器中。

另一种方法是忘记Spring MVC机制并在控制器中手动提交响应:

HandlerInterceptor

请注意void返回代码,以通知Spring响应已在控制器中提交。

作为一个优势,处理仍然发生在同一个线程中,因此您可以完全访问会话作用域属性或Spring MVC或Spring Security使用的任何其他线程局部变量...

答案 1 :(得分:2)

我猜你会使用spring的异步机制 servlet 3.0中引入了异步方法,Spring为它们提供了一些支持 基本上......你提出要求;请求由服务器处理,然后在后台,新线程管理请求数据 这是一个有用的链接(至少我希望:))http://spring.io/blog/2012/05/10/spring-mvc-3-2-preview-making-a-controller-method-asynchronous/

答案 2 :(得分:0)

您应该使用HandlerInterceptor。但是代码比预期的要复杂得多。所以,这里有一个代码建议,通过将整个解决方案放在一个类中来简化它:

@RequestMapping(value = Connectors.CONNECTOR_HEARTBEAT, method = RequestMethod.POST)
public ResponseEntity<String> doSomething(@RequestBody List<Message> messages) {
    HttpStatus code = (messages!=null && !messages.isEmpty()) ? HttpStatus.OK
            : HttpStatus.NOT_FOUND;

    result.set(res); // Save the object to be used after response

    return new ResponseEntity<String>(res, code);
}

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

@Bean
public HandlerInterceptor interceptor() {
    return new HandlerInterceptor() {
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            // Get the saved object and clean for the next request
            String res = result.get();
            result.set(null);

            // TODO Your code to be executed after response.
        }
    };
}

答案 3 :(得分:0)

您可以使用@Async

@RequestMapping(value = Connectors.CONNECTOR_HEARTBEAT, method = 
      RequestMethod.POST)
public ResponseEntity<String> doSomething(@RequestBody List<Message> 
      messages) {
    do();
    HttpStatus code = (messages!=null && !messages.isEmpty()) ? HttpStatus.OK
        : HttpStatus.NOT_FOUND;
     return new ResponseEntity<String>(res, code);

}

@Async 
void do(){
   //your code
}

在Java 8中可以正常工作

答案 4 :(得分:-2)

返回语句后不能有代码。试试这个:

@RequestMapping(value = Connectors.CONNECTOR_HEARTBEAT, method = RequestMethod.POST)
public ResponseEntity<String> doSomething(@RequestBody List<Message> messages) {
    HttpStatus code = (messages!=null && !messages.isEmpty()) ? HttpStatus.OK
            : HttpStatus.NOT_FOUND;
    ResponseEntity<String> response = new ResponseEntity<String>(res, code);
   // code here
   return respone
}