几种异步接口实现demo
package org.dromara.controller.app;import cn.dev33.satoken.annotation.SaIgnore;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
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;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.Map;
import java.util.concurrent.*;
@Slf4j
@SaIgnore
@RestController
@RequestMapping("testAsync")
public class TestAsyncController {private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);private static final Map<String, DeferredResult<String>> DEFERRED_RESULT_MAP = new ConcurrentHashMap<>();@GetMapping("/emitter")public ResponseEntity<ResponseBodyEmitter> handle() {ResponseBodyEmitter emitter = new ResponseBodyEmitter();scheduler.scheduleAtFixedRate(() -> {try {emitter.send(String.format("timestamp: %d\n", System.currentTimeMillis()), MediaType.TEXT_PLAIN);} catch (IOException e) {throw new RuntimeException(e);}}, 0, 2, TimeUnit.SECONDS); emitter.onTimeout(emitter::complete);return new ResponseEntity<>(emitter, HttpStatus.OK);}@GetMapping("/sse")public SseEmitter handleSse() {SseEmitter emitter = new SseEmitter();scheduler.scheduleAtFixedRate(() -> {try {SseEmitter.SseEventBuilder event = SseEmitter.event().name("sse").data(String.format("timestamp: %d", System.currentTimeMillis()));emitter.send(event);} catch (IOException e) {emitter.completeWithError(e); }}, 0, 3, TimeUnit.SECONDS);emitter.onTimeout(emitter::complete);return emitter;}@GetMapping("/stream")public ResponseEntity<StreamingResponseBody> handleStream() throws MalformedURLException {Resource resource = new UrlResource("https://blog.csdn.net/lcj_star/");StreamingResponseBody stream = outputStream -> {try (InputStream inputStream = resource.getInputStream()) {byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = inputStream.read(buffer)) != -1) {outputStream.write(buffer, 0, bytesRead);}} catch (IOException e) {log.error("文件读取失败: {}", e.getMessage(), e);}};HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.setContentDispositionFormData("attachment", resource.getFilename()); return ResponseEntity.ok().headers(headers).body(stream);}@GetMapping("/callAble")public Callable<String> testCallAble() {return () -> {Thread.sleep(4000); return "hello"; };}@GetMapping("/webAsyncTask")public WebAsyncTask<String> webAsyncTask() {WebAsyncTask<String> result = new WebAsyncTask<>(30003, () -> {return "success"; });result.onTimeout(() -> {log.info("timeout callback");return "timeout callback";});result.onCompletion(() -> log.info("finish callback"));return result;}@GetMapping("/deferredResult")public DeferredResult<String> testDeferredResult() {DeferredResult<String> deferredResult = new DeferredResult<>();DEFERRED_RESULT_MAP.put("demo", deferredResult); return deferredResult; }@GetMapping("/setDeferredResult")public String testSetDeferredResult() {DeferredResult<String> deferredResult = DEFERRED_RESULT_MAP.get("demo"); boolean flag = deferredResult.setResult("DeferredResult hello"); if (!flag) {log.info("结果已经被处理,此次操作无效");}return "success";}
}
总结
技术 | 适用场景 | 特点 |
---|
ResponseBodyEmitter | 持续文本流传输 | 手动控制发送时机 |
SseEmitter | 服务端事件推送 | SSE协议支持 |
StreamingResponseBody | 文件流传输 | 适用于大文件下载 |
Callable | 简单异步处理 | 自动包装异步执行 |
WebAsyncTask | 需回调控制 | 支持超时/完成回调 |
DeferredResult | 外部触发 | 可跨请求设置结果 |