`DeferredResult`用法简单介绍

简介: `DeferredResult`用法简单介绍

简介

DeferredResult是Spring Framework中用于处理异步请求的一个类,通常与Spring MVC的Controller一起使用。它允许控制器在请求处理完成后,异步地生成响应,而不必阻塞线程等待结果。这对于处理需要耗时的操作或长时间等待外部资源响应的请求非常有用。

public class DeferredResult<T> {
    private static final Object RESULT_NONE = new Object();
    private static final Log logger = LogFactory.getLog(DeferredResult.class);
    @Nullable
    private final Long timeoutValue;
    private final Supplier<?> timeoutResult;
    private Runnable timeoutCallback;
    private Consumer<Throwable> errorCallback;
    private Runnable completionCallback;
    private DeferredResultHandler resultHandler;
    private volatile Object result;
    private volatile boolean expired;
    public DeferredResult() {
        this((Long)null, (Supplier)(() -> {
            return RESULT_NONE;
        }));
    }
    public DeferredResult(Long timeoutValue) {
        this(timeoutValue, () -> {
            return RESULT_NONE;
        });
    }
    public DeferredResult(@Nullable Long timeoutValue, Object timeoutResult) {
        this.result = RESULT_NONE;
        this.timeoutValue = timeoutValue;
        this.timeoutResult = () -> {
            return timeoutResult;
        };
    }
    public DeferredResult(@Nullable Long timeoutValue, Supplier<?> timeoutResult) {
        this.result = RESULT_NONE;
        this.timeoutValue = timeoutValue;
        this.timeoutResult = timeoutResult;
    }
    public final boolean isSetOrExpired() {
        return this.result != RESULT_NONE || this.expired;
    }
    public boolean hasResult() {
        return this.result != RESULT_NONE;
    }
    @Nullable
    public Object getResult() {
        Object resultToCheck = this.result;
        return resultToCheck != RESULT_NONE ? resultToCheck : null;
    }
    @Nullable
    final Long getTimeoutValue() {
        return this.timeoutValue;
    }
    public void onTimeout(Runnable callback) {
        this.timeoutCallback = callback;
    }
    public void onError(Consumer<Throwable> callback) {
        this.errorCallback = callback;
    }
    public void onCompletion(Runnable callback) {
        this.completionCallback = callback;
    }
    public final void setResultHandler(DeferredResultHandler resultHandler) {
        Assert.notNull(resultHandler, "DeferredResultHandler is required");
        if (!this.expired) {
            Object resultToHandle;
            synchronized(this) {
                if (this.expired) {
                    return;
                }
                resultToHandle = this.result;
                if (resultToHandle == RESULT_NONE) {
                    this.resultHandler = resultHandler;
                    return;
                }
            }
            try {
                resultHandler.handleResult(resultToHandle);
            } catch (Throwable var5) {
                logger.debug("Failed to process async result", var5);
            }
        }
    }
    public boolean setResult(T result) {
        return this.setResultInternal(result);
    }
    private boolean setResultInternal(Object result) {
        if (this.isSetOrExpired()) {
            return false;
        } else {
            DeferredResultHandler resultHandlerToUse;
            synchronized(this) {
                if (this.isSetOrExpired()) {
                    return false;
                }
                this.result = result;
                resultHandlerToUse = this.resultHandler;
                if (resultHandlerToUse == null) {
                    return true;
                }
                this.resultHandler = null;
            }
            resultHandlerToUse.handleResult(result);
            return true;
        }
    }
    public boolean setErrorResult(Object result) {
        return this.setResultInternal(result);
    }
    final DeferredResultProcessingInterceptor getInterceptor() {
        return new DeferredResultProcessingInterceptor() {
            public <S> boolean handleTimeout(NativeWebRequest request, DeferredResult<S> deferredResult) {
                boolean continueProcessing = true;
                boolean var12 = false;
                try {
                    var12 = true;
                    if (DeferredResult.this.timeoutCallback != null) {
                        DeferredResult.this.timeoutCallback.run();
                        var12 = false;
                    } else {
                        var12 = false;
                    }
                } finally {
                    if (var12) {
                        Object value = DeferredResult.this.timeoutResult.get();
                        if (value != DeferredResult.RESULT_NONE) {
                            continueProcessing = false;
                            try {
                                DeferredResult.this.setResultInternal(value);
                            } catch (Throwable var13) {
                                DeferredResult.logger.debug("Failed to handle timeout result", var13);
                            }
                        }
                    }
                }
                Object valuex = DeferredResult.this.timeoutResult.get();
                if (valuex != DeferredResult.RESULT_NONE) {
                    continueProcessing = false;
                    try {
                        DeferredResult.this.setResultInternal(valuex);
                    } catch (Throwable var14) {
                        DeferredResult.logger.debug("Failed to handle timeout result", var14);
                    }
                }
                return continueProcessing;
            }
            public <S> boolean handleError(NativeWebRequest request, DeferredResult<S> deferredResult, Throwable t) {
                try {
                    if (DeferredResult.this.errorCallback != null) {
                        DeferredResult.this.errorCallback.accept(t);
                    }
                } finally {
                    try {
                        DeferredResult.this.setResultInternal(t);
                    } catch (Throwable var10) {
                        DeferredResult.logger.debug("Failed to handle error result", var10);
                    }
                }
                return false;
            }
            public <S> void afterCompletion(NativeWebRequest request, DeferredResult<S> deferredResult) {
                DeferredResult.this.expired = true;
                if (DeferredResult.this.completionCallback != null) {
                    DeferredResult.this.completionCallback.run();
                }
            }
        };
    }
    @FunctionalInterface
    public interface DeferredResultHandler {
        void handleResult(Object result);
    }
}

案例

下面是DeferredResult的主要用法和示例说明:

  1. 异步处理请求:
    控制器方法可以返回DeferredResult,使得该方法可以异步地处理请求。这样,当请求被接收后,控制器方法不会立即返回响应,而是在后台进行处理,最终设置DeferredResult的结果。这允许控制器线程立即释放,从而提高服务器的并发性能。
@RestController
public class MyController {
    @Autowired
    private MyAsyncService asyncService;
    @GetMapping("/async-operation")
    public DeferredResult<String> handleAsyncRequest() {
        DeferredResult<String> deferredResult = new DeferredResult<>();
        asyncService.performAsyncOperation(result -> {
            deferredResult.setResult(result);
        });
        return deferredResult;
    }
}
  1. 设置结果:
    异步处理完成后,通过设置DeferredResult的结果来响应客户端请求。
public class MyAsyncService {
    public void performAsyncOperation(Consumer<String> callback) {
        // 异步处理操作
        String result = ...; // 执行异步操作获取结果
        callback.accept(result);
    }
}
@FunctionalInterface
public interface Consumer<T> {
    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);
    /**
     * Returns a composed {@code Consumer} that performs, in sequence, this
     * operation followed by the {@code after} operation. If performing either
     * operation throws an exception, it is relayed to the caller of the
     * composed operation.  If performing this operation throws an exception,
     * the {@code after} operation will not be performed.
     *
     * @param after the operation to perform after this operation
     * @return a composed {@code Consumer} that performs in sequence this
     * operation followed by the {@code after} operation
     * @throws NullPointerException if {@code after} is null
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

在这个示例中,Consumer<String>是一个函数式接口,它定义了一个接收一个参数并且不返回任何结果的操作。具体来说,Consumer<String>表示接受一个String类型的参数,并对该参数进行处理,但不返回任何结果。

在MyAsyncService类中的performAsyncOperation方法中,它接受一个Consumer<String>类型的参数callback。在异步处理操作完成后,会调用callback.accept(result)方法,将异步操作的结果result传递给这个callback。

这样做的好处是,MyAsyncService类不需要知道具体的异步操作是如何实现的,它只需要在异步操作完成后将结果传递给callback,由调用方来定义具体的处理逻辑。这种方式使得代码更加灵活和可扩展,符合面向接口编程的思想。

3. 超时处理:

可以设置DeferredResult的超时时间,如果在规定的时间内未设置结果,可以触发超时处理。

@GetMapping("/async-operation")
public DeferredResult<String> handleAsyncRequest() {
    DeferredResult<String> deferredResult = new DeferredResult<>(5000L); // 设置5秒超时
    asyncService.performAsyncOperation(result -> {
        deferredResult.setResult(result);
    });
    return deferredResult;
}
  1. 错误处理:
    可以注册回调函数来处理异常或错误情况。
@GetMapping("/async-operation")
public DeferredResult<String> handleAsyncRequest() {
    DeferredResult<String> deferredResult = new DeferredResult<>();
    deferredResult.onError(e -> {
        // 处理错误情况
    });
    asyncService.performAsyncOperation(result -> {
        deferredResult.setResult(result);
    });
    return deferredResult;
}

总的来说,DeferredResult提供了一种方便的方式来处理异步请求,使得服务器能够高效地处理大量并发请求,并且可以灵活地处理超时和错误情况。

相关文章
|
1天前
|
网络协议 安全 Linux
在IntelliJ IDEA中使用固定公网地址远程SSH连接服务器环境进行开发
在IntelliJ IDEA中使用固定公网地址远程SSH连接服务器环境进行开发
7 2
|
18天前
|
弹性计算 运维 应用服务中间件
ECS使用有感
ECS使用有感
|
18天前
|
UED
带您一步步构建一个具有复杂布局的电商详情页,涵盖页面结构规划、样式设计以及交互效果的实现
【6月更文挑战第14天】构建复杂布局的电商详情页涉及页面结构规划、样式设计和交互效果实现。首先,规划页面结构,包括顶部导航栏、商品图片展示区、商品信息区、用户评价区和相关商品推荐区。接着,进行样式设计,注重色彩搭配、字体选择、布局与间距以及图片处理。例如,使用固定顶部导航栏,轮播图展示商品图片,分块展示商品信息和评价,以及设计相关商品推荐区。最后,实现交互效果,如图片放大、添加到购物车按钮、滚动监听和评论互动,提升用户体验。实际开发时需根据需求和规范进行调整,保证跨设备兼容性。
42 1
|
14天前
|
安全 C++
C++一分钟之-控制流:if语句与条件判断
【6月更文挑战第18天】在C++中,`if`语句是控制流的核心,用于条件判断和决策。简单`if`检查条件是否为真,执行相应代码;`if-else`添加了否定分支;而`if-else if-else`链处理多个条件。常见问题包括真假值混淆(非零为真)、逻辑运算符误用、缺少可读性以及边界条件忽视。通过明确比较、理解逻辑运算符和强化边界检查,可以提高代码质量。示例展示了根据成绩输出不同反馈,强调了逻辑的清晰性和可维护性。掌握`if`语句是编写有效逻辑的关键。
33 13
|
18天前
|
SQL Oracle 关系型数据库
|
14天前
|
人工智能 监控 并行计算
Stable Diffusion火影数据集训练:SwanLab可视化训练
**使用Stable Diffusion 1.5模型训练火影忍者风格的文生图模型。在22GB显存的GPU上,通过Huggingface的`lambdalabs/naruto-blip-captions`数据集进行训练,利用SwanLab进行监控。所需库包括`swanlab`, `diffusers`, `datasets`, `accelerate`, `torchvision`, `transformers`。代码、日志和更多资源可在GitHub和SwanLab找到。训练涉及数据下载、模型配置、训练过程可视化及结果评估。**
Stable Diffusion火影数据集训练:SwanLab可视化训练
|
19天前
|
消息中间件 监控 API
构建微服务架构:从理论到实践的全面指南
本文将深入探讨微服务架构的设计原则、实施步骤和面临的挑战。与传统的单体架构相比,微服务通过其独立性、可伸缩性和灵活性,为现代应用开发提供了新的视角。文章将介绍如何从零开始规划和部署一个微服务系统,包括选择合适的技术栈、处理数据一致性问题以及实现服务间通信。此外,我们还将讨论在迁移至微服务架构过程中可能遇到的技术和组织挑战,以及如何克服这些难题以实现顺利过渡。
|
15天前
|
前端开发 JavaScript Android开发
移动应用开发的未来:跨平台框架与原生开发的融合
在移动应用的世界里,开发者面临着一个永恒的问题:是选择高效的跨平台解决方案,还是坚持性能卓越的原生开发?本文将探讨移动应用开发的最新趋势,特别是跨平台框架和原生开发如何相互补充,共同塑造未来的移动应用生态。我们将深入了解Flutter、React Native等框架的优势,并分析它们如何与Android和iOS原生开发环境相结合,创造出既快速又高效的开发流程。
|
5天前
|
机器学习/深度学习 人工智能 自然语言处理
影中的ai技术
【6月更文挑战第27天】电影中的ai技术
220 65
|
7天前
|
机器学习/深度学习 自然语言处理 算法
深度学习在自然语言处理中的进展与应用
本文探讨了深度学习技术在自然语言处理领域的最新进展和应用。通过分析深度学习模型的发展历程及其在文本分类、情感分析、语义理解等任务中的成功案例,展示了这些技术如何推动了自然语言处理的前沿应用。同时,文章还讨论了当前技术面临的挑战以及未来发展的趋势。
38 11