简体   繁体   English

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

[英]Spring Controller start processing after response is sent

I am using a Spring MVC controller and want to start the execution of a task in a new thread.我正在使用 Spring MVC 控制器并希望在新线程中开始执行任务。 However the task should not start immediately but only after the response has been sent to the client.然而,任务不应立即开始,而应在响应发送到客户端后开始。

The sequence - in strict temporal order:序列 - 严格按照时间顺序:

  1. request要求
  2. return new ResponseEntity ... / client receives HTTP status 200 OK. return new ResponseEntity ... / 客户端收到 HTTP 状态 200 OK。
  3. processing of the task begins.任务的处理开始。

How do I achieve this?我如何实现这一目标?

I wanted to use Spring's async abstraction by calling a method annotated with @Async, but it does not guarantee that the new thread waits for the response to be sent first.我想通过调用一个用@Async 注释的方法来使用Spring 的异步抽象,但它不保证新线程首先等待响应被发送。

You can use an interceptor for that.您可以为此使用拦截器。 The order of events for handling a request in Spring MVC is:在 Spring MVC 中处理请求的事件顺序是:

  • DispatcherServlet get a Request, Response pair and determines the handling DispatcherServlet 获取请求、响应对并确定处理
  • [optional] interceptors preHandle are called (with option to stop processing) [可选] 拦截器 preHandle 被调用(带有停止处理的选项)
  • controller is called控制器被调用
  • [optional] interceptors postHandle are called [可选] 拦截器 postHandle 被调用
  • ViewResolver and view do the actual Response processing and send the response ViewResolver 和 view 做实际的 Response 处理并发送响应
  • [optional] interceptors afterCompletion are called [可选] 拦截器 afterCompletion 被调用

The above is over simplified and is just aimed at showing that interceptor afterCompletion methods are called after the response has been sent to client, with following signature :以上过于简化,只是为了表明在响应发送到客户端后afterCompletion拦截器afterCompletion方法,具有以下签名:

void afterCompletion(HttpServletRequest request,
                     HttpServletResponse response,
                     Object handler,
                     Exception ex)
                     throws Exception

In that method, you can test the occurence of an exception and the correctness of the response ( ex == null && response.getStatus() == HttpServletResponse.SC_OK ) before starting your processing.在该方法中,您可以在开始处理之前测试异常的发生和响应的正确性( ex == null && response.getStatus() == HttpServletResponse.SC_OK )。

If your "after respond is sent" requirement is fulfilled with "after the view has been rendered" you may use an implementation of HandlerInterceptor .如果您的“发送响应后”要求满足“在呈现视图之后”,您可以使用HandlerInterceptor的实现。 For an example cf.例如,参见。 Spring 3 MVC Interceptor tutorial with example , triggering your job in afterCompletion . Spring 3 MVC 拦截器教程与示例,在afterCompletion触发您的工作。

If your job needs to be triggered "after it hit the wire", I'd like to know why.如果您的工作需要“在它碰到电线后”触发,我想知道为什么。

The HandlerInterceptor is the solution, but the code get a little bit more complex than expected. HandlerInterceptor是解决方案,但代码比预期的要复杂一些。

Here's a code suggestion to make it simpler by putting the whole solution in a single class:这是一个代码建议,通过将整个解决方案放在一个类中来使其更简单:

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.
        }
    });
}

You could add the task to a blocking queue, before the response entity is created.在创建响应实体之前,您可以将任务添加到阻塞队列中。 Let a task executor run periodically (every x seconds) over the queue and poll for tasks.让任务执行器定期(每 x 秒)在队列上运行并轮询任务。 If a task is found, it will be executed.如果找到一个任务,它将被执行。 If not, the thread finishes its run method and waits for the next run (in x seconds).如果没有,线程完成其 run 方法并等待下一次运行(以 x 秒为单位)。

How to run a task periodically: http://www.mkyong.com/java/how-to-run-a-task-periodically-in-java/如何定期运行任务: http : //www.mkyong.com/java/how-to-run-a-task-periodically-in-java/

Inject the queue as dependency in both the controller and the task executor service.将队列作为依赖项注入控制器和任务执行器服务。 This should be an easy solution to start with.这应该是一个简单的解决方案。

In this szenario you can't be sure, that the client receives the request.在这个场景中,您无法确定客户端是否收到了请求。 But if you want to be safe(r), add a due date to your task object with a sufficient offset (eg current time + 30 seconds).但是,如果您想安全(r),请为您的任务对象添加一个具有足够偏移量的截止日期(例如当前时间 + 30 秒)。 Let the task executor check if the due date of the polled task is now or in the past.让任务执行器检查轮询任务的截止日期是现在还是过去。 Otherwise ignore the task for this run.否则忽略此运行的任务。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Spring MVC在Rest Controller上调用Web服务并返回xml响应后,如何在发送响应后执行其他功能? - Spring MVC after calling webservice at Rest Controller and returning xml response how can I execute other function after response sent? Spring MVC:如何修改从控制器发送的json响应 - Spring MVC: How to modify json response sent from controller Spring Batch在Spring Boot中完成作业后发送响应 - Sent Response after Spring Batch completed Job in Spring Boot Spring WebSocket-消息被控制器发送后丢失 - Spring WebSocket - messages lost after being sent by controller Java / Spring&gt;在请求中未发送任何正文时,使用@RequestBody处理控制器方法的错误请求响应 - Java/Spring > Handle Bad Request response for controller method with @RequestBody when no body is sent in request 服务器发送事件 Spring Webflux 返回事件名称以响应其余控制器 - Server Sent Event Spring Webflux return event name in response from rest controller 如何在Flowable中使用Spring Boot启动事件后返回响应 - How to return response after start event in Flowable with Spring Boot 如何在使用Spring返回响应后调用异步控制器逻辑? - How to invoke async controller logic after returning response using Spring? 异步 Spring MVC 控制器方法后的日志响应正文 - Log response body after asynchronous Spring MVC controller method 在Spring Controller中使用响应重定向 - Redirect with a Response in Spring Controller
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM