2015-08-18 3 views
4

Скажите, что моя функция контроллера пружины получает большой объем данных. Я хочу вернуть 200 OK, учитывая, что данные структурированы правильно, и после этого Я хочу выполнить обработку, которая может занять некоторое время.Как отправить ответ перед действиями весной mvc

Насколько я понимаю, единственный способ отправки ответа - return command. Но я не хочу останавливать функцию отправки ответа.

Существуют ли другие способы отправки ответа клиенту в середине функции?

Создание нового потока прокрутки очевидно, но другие языки (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?? 
} 
+0

использовать метод @Async, который мог бы обернуть все, что вы хотите запустить, он будет обрабатываться с помощью другого потока – freakman

+0

[Это может помочь] (http://stackoverflow.com/a/17176660/3143670) –

ответ

6

Вы можете, конечно, обработать после отправки ответа. Более общий способ заключается в использовании метода afterCompletion для HandlerInterceptor. По конструкции он будет выполнен после того, как ответ будет отправлен клиенту, но он заставит вас разделить логику на 2 компонента: до в контроллере, а после - часть в перехватчике.

Альтернативный способ забыть Spring MVC машину и вручную зафиксировать отклик в контроллере:

@RequestMapping(value = Connectors.CONNECTOR_HEARTBEAT, method = RequestMethod.POST) 
public void doSomething(@RequestBody List<Message> messages, HttpServletResponse response) { 
    int code = (messages!=null && !messages.isEmpty()) ? HttpServletResponse.SC_OK 
      : HttpServletResponse.SC_NOT_FOUND; 
    if (code != HttpServletResponse.SC_OK) { 
     response.sendError(code, res); 
     return; 
    } 
    java.io.PrintWriter wr = response.getWriter(); 
    response.setStatus(code); 
    wr.print(res); 
    wr.flush(); 
    wr.close(); 

    // Now it it time to do the long processing 
    ... 
} 

Примечание пустота код возврата уведомить Spring, что ответ был совершен в контроллере.

В качестве побочного преимущество, обработка по-прежнему происходит в том же потоке, поэтому у вас есть полный доступ к сеансу области видимости атрибутов или других потоков локальные переменные, используемые Spring MVC или Spring Security ...

+0

Если запрос от двух разных пользователей, то он будет использовать одну и ту же переменную или другую для разных пользователей? –

0

У вас не может быть кода после оператора возврата. Попробуйте следующее:

@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 
} 
+0

Но ответ возвращается только после завершения процесса в вашем коде. –

+0

Да. Если код не запускает новый поток, который выполняет этот процесс. Таким образом, поток будет выполняться отдельно, и при вызове будет вызван возврат. –

+1

Сказать, что запуск новой нити в контроллере не рекомендуется. –

0

Интересно, если ваш дизайн немного испорчен. То есть, основываясь на том, что вы сказали до сих пор.

Как я вижу, вы должны получить данные и сохранить их как-нибудь, сказать «ОК» клиенту, а затем иметь отдельный рабочий поток, пережевывать все, что было отправлено, в фоновом режиме.

+1

Это действительно вопрос выбора, если вы хотите многопоточность env или нет.Для каждого подхода есть плюсы и минусы (например, подход nodejs). везде, где я могу избежать открытия нового потока - я это делаю. –

2

Я думаю, вы mau использовать асинхронный механизм пружины Асинхронные методы были введены в сервлет 3.0, а Spring предлагает некоторую поддержку им В основном ... вы делаете запрос; запрос обрабатывается сервером, а затем в фоновом режиме новый поток управляет данными requesta Здесь полезная ссылка (по крайней мере, я надеюсь :)) http://spring.io/blog/2012/05/10/spring-mvc-3-2-preview-making-a-controller-method-asynchronous/

Смежные вопросы