springboot中异步接口实现所有方式_20250501

几种异步接口实现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.*;

/**
 * 异步接口实现方式大全
 * 演示Spring Boot中多种异步处理方案:
 * 1. 响应体发射器(ResponseBodyEmitter)
 * 2. 服务器发送事件(SSE)
 * 3. 文件流传输
 * 4. Callable异步调用
 * 5. WebAsyncTask
 * 6. 延迟结果(DeferredResult)
 */
@Slf4j // Lombok生成日志对象
@SaIgnore // 忽略权限校验
@RestController // REST控制器
@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<>();

    /**
     * 使用ResponseBodyEmitter实现持续通信
     * 每2秒向客户端发送时间戳消息
     */
    @GetMapping("/emitter")
    public ResponseEntity<ResponseBodyEmitter> handle() {
        // 创建响应发射器
        ResponseBodyEmitter emitter = new ResponseBodyEmitter();

        // 定时任务:每2秒发送一次消息
        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); // 初始延迟0s,间隔2s

        // 设置10秒超时处理
        // 关闭连接
        emitter.onTimeout(emitter::complete);

        return new ResponseEntity<>(emitter, HttpStatus.OK);
    }

    /**
     * 使用SseEmitter实现服务器发送事件(SSE)
     * 每3秒推送自定义事件消息
     */
    @GetMapping("/sse")
    public SseEmitter handleSse() {
        SseEmitter emitter = new SseEmitter();

        // 定时事件推送(3秒间隔)
        scheduler.scheduleAtFixedRate(() -> {
            try {
                // 构建SSE事件:事件名+数据
                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);

        // 15秒超时处理
        // 关闭连接
        emitter.onTimeout(emitter::complete);

        return emitter;
    }

    /**
     * 文件流式传输示例
     * 实现大文件下载(模拟)
     */
    @GetMapping("/stream")
    public ResponseEntity<StreamingResponseBody> handleStream() throws MalformedURLException {
        // 创建远程资源对象(演示用URL)
        Resource resource = new UrlResource("https://blog.youkuaiyun.com/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);
    }

    /**
     * Callable异步处理示例
     * 模拟耗时操作后返回结果
     */
    @GetMapping("/callAble")
    public Callable<String> testCallAble() {
        return () -> {
            Thread.sleep(4000); // 模拟4秒耗时
            return "hello"; // 返回结果
        };
    }

    /**
     * WebAsyncTask异步处理示例
     * 支持超时和完成回调
     */
    @GetMapping("/webAsyncTask")
    public WebAsyncTask<String> webAsyncTask() {
        // 创建异步任务(超时时间30003ms)
        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外部触发可跨请求设置结果
Spring Boot中,可以通过多种方式实现异步查询接口。以下是一种常见的方法,使用`@Async`注解和`CompletableFuture`类来实现异步查询: 1. **启用异步支持**:在Spring Boot应用的主类上添加`@EnableAsync`注解,以启用异步方法支持。 ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableAsync; @SpringBootApplication @EnableAsync public class AsyncApplication { public static void main(String[] args) { SpringApplication.run(AsyncApplication.class, args); } } ``` 2. **创建异步服务**:在服务类中定义一个异步方法,并使用`@Async`注解标记该方法。确保该服务类被Spring管理(例如,使用`@Service`注解)。 ```java import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import java.util.concurrent.CompletableFuture; @Service public class AsyncService { @Async public CompletableFuture<String> asyncQuery() { // 模拟异步操作,例如数据库查询或外部API调用 try { Thread.sleep(5000); // 模拟耗时操作 } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return CompletableFuture.completedFuture("Async Result"); } } ``` 3. **创建控制器**:在控制器中调用异步服务的方法,并处理返回的`CompletableFuture`。 ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.concurrent.CompletableFuture; @RestController public class AsyncController { @Autowired private AsyncService asyncService; @GetMapping("/async-query") public CompletableFuture<String> asyncQuery() { return asyncService.asyncQuery(); } } ``` 通过上述步骤,你就可以在Spring Boot应用中实现一个异步查询接口。访问`/async-query`接口时,服务器会立即返回`CompletableFuture`,而不会阻塞请求线程。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值