Spring MVC 处理异步请求超时及其异常

发布于 2025-02-24 23:16:28 字数 4991 浏览 5 评论 0

Spring(Integration)中几个常用 TaskExecutor 的内置实现:

  • SyncTaskExecutor :不会异步执行,在发起线程中执行,适合非多线程场景
  • SimpleAsyncTaskExecutor :默认的异步请求任务执行器。不重用任何线程,每次执行请求都会创建一个新的(但可以设置上限)
  • ThreadPoolTaskExecutor最常用的一个线程池执行器,可以设置线程大小、缓冲队列、空闲线程、存活时间等
  • ConcurrentTaskExecutor :对 java.util.concurrent.Executor 的进一步封装,提供比 ThreadPoolTaskExecutor 更灵活的配置
package net.wuxianjie.demo.controller;

import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import net.wuxianjie.demo.dto.UserDto;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.context.request.async.WebAsyncTask;

@RestController
@RequestMapping("/users")
public class UserController {

  @ExceptionHandler(Exception.class)
  public ResponseEntity<String> handle(Exception e) {
    return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
  }

  @PostMapping("/async_1")
  public DeferredResult<UserDto> addUser1(@RequestBody UserDto userDto) {

    DeferredResult<UserDto> deferredResult = new DeferredResult<>(3000L);
    deferredResult.onTimeout(() -> {
      deferredResult.setErrorResult(new Exception("DeferredResult 异步请求超时"));
    });

    new Thread(() -> {
      try {
        TimeUnit.SECONDS.sleep(5);
        userDto.setUserName("异步 DeferredResult:" + userDto.getUserName());
        deferredResult.setResult(userDto);
      } catch (InterruptedException ignore) {
      }
    }).start();

    return deferredResult;
  }

  @PostMapping("/async_2")
  public WebAsyncTask<UserDto> addUser2(@RequestBody UserDto userDto) {

    WebAsyncTask<UserDto> webAsyncTask = new WebAsyncTask<>(3000, () -> {
      TimeUnit.SECONDS.sleep(5);
      userDto.setUserName("异步 WebAsyncTask:" + userDto.getUserName());
      return userDto;
    });

    webAsyncTask.onTimeout(() -> {
      throw new Exception("WebAsyncTask 异步请求超时");
    });

    return webAsyncTask;
  }

  @PostMapping("/sync")
  public UserDto addUserSync(@RequestBody UserDto userDto) {
    userDto.setUserName("同步无延迟:" + userDto.getUserName());
    return userDto;
  }

  @PostMapping("/sync_delay")
  public UserDto addUserSyncDelay(@RequestBody UserDto userDto) throws InterruptedException {
    TimeUnit.SECONDS.sleep(5);
    userDto.setUserName("同步有延迟:" + userDto.getUserName());
    return userDto;
  }
}
<!DOCTYPE html>
<html>
  <head lang="zh">
    <meta charset="UTF-8">
    <title>Test Index</title>
  </head>
  <body>

    <button onclick="sendAjax1()">异步提交(DeferredResult)</button>
    <button onclick="sendAjax2()">异步提交(Callable)</button>
    <button onclick="send()">同步提交(无延迟)</button>
    <button onclick="sendAndDelayResponse()">同步提交(有延迟)</button>

    <script type="text/javascript">
      const params = {
        "user_id": "101",
        "user_name": "吴仙杰",
        "birthday": "2020-06-11 09:05:00"
      };

      function sendAjax1() {
        fetch("http://localhost:8000/users/async_1", {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify(params)
        }).then(response => {
          response.json().then(data => console.log(data));
        });
      }

      function sendAjax2() {
        fetch("http://localhost:8000/users/async_2", {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify(params)
        }).then(response => {
          response.json().then(data => console.log(data));
        });
      }

      function send() {
        fetch("http://localhost:8000/users/sync", {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify(params)
        }).then(response => {
          response.json().then(data => console.log(data));
        });
      }

      function sendAndDelayResponse() {
        fetch("http://localhost:8000/users/sync_delay", {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify(params)
        }).then(response => {
          response.json().then(data => console.log(data));
        });
      }
    </script>
  </body>
</html>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

撩心不撩汉

暂无简介

文章
评论
27 人气
更多

推荐作者

闻呓

文章 0 评论 0

深府石板幽径

文章 0 评论 0

mabiao

文章 0 评论 0

枕花眠

文章 0 评论 0

qq_CrTt6n

文章 0 评论 0

红颜悴

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文