Spring MVC 处理异步请求超时及其异常
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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论