探索 Java 中的 DeferredResult<Object>

news2024/11/26 1:35:44

个人名片
在这里插入图片描述
🎓作者简介:java领域优质创作者
🌐个人主页:码农阿豪
📞工作室:新空间代码工作室(提供各种软件服务)
💌个人邮箱:[2435024119@qq.com]
📱个人微信:15279484656
🌐个人导航网站:www.forff.top
💡座右铭:总有人要赢。为什么不能是我呢?

  • 专栏导航:

码农阿豪系列专栏导航
面试专栏:收集了java相关高频面试题,面试实战总结🍻🎉🖥️
Spring5系列专栏:整理了Spring5重要知识点与实战演练,有案例可直接使用🚀🔧💻
Redis专栏:Redis从零到一学习分享,经验总结,案例实战💐📝💡
全栈系列专栏:海纳百川有容乃大,可能你想要的东西里面都有🤸🌱🚀

目录

      • 探索 Java 中的 DeferredResult<Object>
        • 1. 什么是 DeferredResult<Object>?
        • 2. 使用场景
        • 3. 基本使用方法
          • 3.1 配置异步支持
          • 3.2 控制器方法中使用 DeferredResult<Object>
          • 3.3 处理超时和错误
        • 4. 高级使用方法
          • 4.1 结合异步结果处理器
          • 4.2 使用 DeferredResult 结合 Spring WebFlux
        • 5. 实际应用案例
          • 案例一:文件上传
          • 案例二:调用外部服务
        • 6. 结论

探索 Java 中的 DeferredResult

在现代 Web 应用程序开发中,异步处理是提升应用性能和响应速度的重要手段。Java 提供了多种方式来实现异步处理,其中 DeferredResult<Object> 是 Spring 框架中用于处理异步请求的一种强大工具。本文将深入探讨 DeferredResult<Object> 的概念、使用场景以及具体实现方法,帮助开发者更好地理解和应用这一工具。

1. 什么是 DeferredResult?

DeferredResult<Object> 是 Spring MVC 中提供的用于异步请求处理的类。它允许我们将请求的处理逻辑从 Servlet 容器的线程中分离出来,从而避免阻塞 Servlet 容器的线程,提升应用的并发处理能力。

通常情况下,Spring MVC 控制器方法会同步处理 HTTP 请求,并在处理完成后返回一个视图或数据。然而,对于一些需要长时间处理的请求,如果同步处理会导致线程阻塞,进而影响服务器的性能和响应速度。在这种情况下,DeferredResult<Object> 提供了一种优雅的异步处理方式。

2. 使用场景

DeferredResult<Object> 适用于以下场景:

  • 长时间处理的请求:例如,调用外部服务、执行复杂计算或处理大文件上传等需要较长时间才能完成的操作。
  • 提升并发处理能力:通过异步处理,可以释放 Servlet 容器的线程,提升服务器的并发处理能力。
  • 避免线程阻塞:在处理长时间操作时,避免线程阻塞,提高系统的整体性能。
3. 基本使用方法

下面通过一个简单的示例,演示如何在 Spring MVC 中使用 DeferredResult<Object> 处理异步请求。

3.1 配置异步支持

首先,需要确保 Spring MVC 支持异步请求处理。在 Spring 配置类或 XML 配置文件中启用异步支持:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    // 其他配置
}
3.2 控制器方法中使用 DeferredResult

在控制器方法中返回 DeferredResult<Object>,并在异步处理完成后设置结果:

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 java.util.concurrent.ForkJoinPool;

@RestController
@RequestMapping("/async")
public class AsyncController {

    @GetMapping("/process")
    public DeferredResult<Object> process() {
        DeferredResult<Object> deferredResult = new DeferredResult<>(5000L, "Request Timeout");

        ForkJoinPool.commonPool().submit(() -> {
            try {
                // 模拟长时间处理
                Thread.sleep(3000);
                deferredResult.setResult("Processing complete");
            } catch (InterruptedException e) {
                deferredResult.setErrorResult(e.getMessage());
            }
        });

        return deferredResult;
    }
}

在上述示例中,DeferredResult<Object> 设置了超时时间为 5000 毫秒,并指定了超时后的默认返回值 "Request Timeout"。在 ForkJoinPool 的线程中,模拟了一个长时间处理操作(休眠 3 秒),然后设置了处理结果 "Processing complete"

3.3 处理超时和错误

可以通过设置超时回调和错误回调来处理请求超时和错误情况:

deferredResult.onTimeout(() -> {
    deferredResult.setErrorResult("Request Timeout");
});

deferredResult.onError((Throwable t) -> {
    deferredResult.setErrorResult(t.getMessage());
});
4. 高级使用方法
4.1 结合异步结果处理器

Spring 提供了 CallableDeferredResultProcessingInterceptor 用于进一步增强异步请求处理的功能。可以通过自定义拦截器来处理更多场景,例如在请求开始时记录日志、在请求完成时进行清理等。

import org.springframework.web.context.request.async.DeferredResultProcessingInterceptor;
import org.springframework.web.context.request.async.AsyncRequestInterceptor;

public class CustomDeferredResultInterceptor extends DeferredResultProcessingInterceptor {
    @Override
    public <T> void beforeConcurrentHandling(NativeWebRequest request, DeferredResult<T> deferredResult) {
        // 请求开始时的逻辑
    }

    @Override
    public <T> void afterCompletion(NativeWebRequest request, DeferredResult<T> deferredResult) {
        // 请求完成时的逻辑
    }
}

然后在配置类中注册拦截器:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CustomDeferredResultInterceptor());
    }
}
4.2 使用 DeferredResult 结合 Spring WebFlux

Spring WebFlux 是 Spring 5 引入的响应式编程框架,可以与 DeferredResult 结合使用,以实现更加复杂的异步处理逻辑。

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
import reactor.core.publisher.Mono;

@RestController
public class WebFluxController {

    @GetMapping("/webflux")
    public DeferredResult<Object> handle() {
        DeferredResult<Object> deferredResult = new DeferredResult<>();

        Mono.just("Hello, WebFlux!")
                .doOnSuccess(deferredResult::setResult)
                .doOnError(deferredResult::setErrorResult)
                .subscribe();

        return deferredResult;
    }
}

在这个示例中,我们使用了 Mono 进行异步处理,并将结果设置到 DeferredResult 中。

5. 实际应用案例
案例一:文件上传

在文件上传的场景中,处理大文件可能需要较长时间,使用 DeferredResult<Object> 可以避免阻塞主线程:

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.multipart.MultipartFile;

import java.util.concurrent.ForkJoinPool;

@RestController
public class FileUploadController {

    @PostMapping("/upload")
    public DeferredResult<Object> upload(@RequestParam("file") MultipartFile file) {
        DeferredResult<Object> deferredResult = new DeferredResult<>();

        ForkJoinPool.commonPool().submit(() -> {
            try {
                // 模拟文件处理
                Thread.sleep(5000);
                deferredResult.setResult("File uploaded successfully");
            } catch (InterruptedException e) {
                deferredResult.setErrorResult(e.getMessage());
            }
        });

        return deferredResult;
    }
}
案例二:调用外部服务

在调用外部服务时,响应时间可能较长,使用 DeferredResult<Object> 可以提高系统的并发处理能力:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;

import java.util.concurrent.CompletableFuture;

@RestController
public class ExternalServiceController {

    @GetMapping("/external")
    public DeferredResult<Object> callExternalService() {
        DeferredResult<Object> deferredResult = new DeferredResult<>();

        CompletableFuture.supplyAsync(() -> {
            // 模拟调用外部服务
            try {
                Thread.sleep(4000);
                return "External service response";
            } catch (InterruptedException e) {
                return "Error: " + e.getMessage();
            }
        }).thenAccept(deferredResult::setResult);

        return deferredResult;
    }
}
6. 结论

DeferredResult<Object> 是 Spring MVC 提供的一个强大的异步处理工具,能够有效提高应用程序的并发处理能力,避免长时间操作阻塞主线程。通过本文的介绍,您应该已经了解了 DeferredResult<Object> 的基本概念、使用方法以及实际应用场景。在实际开发中,灵活运用 DeferredResult<Object> 可以大大提升系统的性能和用户体验。希望本文能够帮助您更好地理解和应用这一工具,为您的项目带来更多的价值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1941504.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(POSIX) 文件读写基础

文章目录 &#x1f5c2;️前言&#x1f4c4;ref&#x1f4c4;访问标记&#x1f5c3;️文件访问标记 &#x1f5c2;️Code&#x1f4c4;demo&#x1f4c4;分点讲解&#x1f5c3;️打开/关闭&#x1f5c3;️写&#x1f5c3;️读 &#x1f5c2;️END&#x1f31f;关注我 &#x1f…

C++ 正则库与HTTP请求

正则表达式的概念和语法 用于描述和匹配字符串的工具&#xff0c;通过特定的语法规则&#xff0c;灵活的定义复杂字符串匹配条件 常用语法总结 基本字符匹配 a&#xff1a;匹配字符aabc&#xff1a;匹配字符串abc 元字符&#xff08;特殊含义的字符&#xff09; .&#xff1a;匹…

【医学影像】RK3588+FPGA:满足远程诊疗系统8K音视频编解码及高效传输需求

医学影像 提供基于Intel平台、NXP平台、Rockchip平台的核心板、Mini-ITX主板、PICO-ITX主板以及工业整机等计算机硬件。产品板载内存&#xff0c;集成超高清编码/解码视频引擎&#xff0c;具有出色的数据处理能力和图形处理能力&#xff0c;功能高集成&#xff0c;可应用于超声…

可信推荐系统论文分享-1

《Debiasing Recommendation by Learning Identifiable Latent Confounders》

openmv学习笔记(24电赛备赛笔记)

#openmv简介 openmv一种小型&#xff0c;可编程机器视觉摄像头&#xff0c;设计应用嵌入式应用和计算边缘&#xff0c;是图传模块&#xff0c;或者认为是一种&#xff0c;具有图像处理功能的单片机&#xff0c;提供多种接口&#xff08;I2C SPI UART CAN ADC DAC &#xff0…

【BUG】已解决:Uncaught SyntaxError: Unexpected token ‘<‘

已解决&#xff1a;Could not install packages due to an EnvironmentError: [Errno 13] Permission denied 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#xff0c;热衷分享知识&#xff0c;武汉城市开发者社区主理人 …

如何训练出模型的推理规划能力

背景 近期opanai对AGI做了等级划分&#xff1b;等级划分意味着AGI有了一个考核定义&#xff0c;有了升级打怪的评价指标。并给出了目前openai正处在第一级&#xff0c;即将达到第二级的论断。预计在一年或者一年半内实现第二级&#xff0c;可以完成基本问题解决任务的系统。 …

抖音客户端一面

C | 字节抖音客户端一面 Http握手过程 1. 客户端问候(Client Hello) 客户端向服务器发送一个“问候”消息&#xff0c;其中包含客户端支持的SSL/TLS版本、加密算法、压缩方法以及一个随机数。 version 版本号,https也有版本号哦TLS 1.0、TLS 1.1、TLS 1.2等等 random 随机数…

【Linux】进程信号 --- 信号保存

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…

Linux中进程间通信--匿名管道和命名管道

本篇将会进入 Linux 进程中进程间通信&#xff0c;本篇简要的介绍了 Linux 中进程为什么需要通信&#xff0c;进程间通信的常用方式。然后详细的介绍了 Linux 进程间的管道通信方式&#xff0c;管道通信分为匿名管道和命名管道&#xff0c;本篇分别介绍了其实现的原理&#xff…

4.Java Web开发模式(javaBean+servlet+MVC)

Java Web开发模式 一、Java Web开发模式 1.javaBean简介 JavaBeans是Java中一种特殊的类&#xff0c;可以将多个对象封装到一个对象&#xff08;bean&#xff09;中。特点是可序列化&#xff0c;提供无参构造器&#xff0c;提供getter方法和setter方法访问对象的属性。名称中…

顺序 IO 和 随机IO

顺序 IO 和 随机IO 顺序IO 和 随机IO 是计算机存储系统领域中的概念&#xff0c;主要涉及数据的读取和写入方式。这些术语通常在讨论硬盘驱动器&#xff08;HDDs&#xff09;、固态驱动器&#xff08;SSD&#xff09;以及其他存储设备的性能时使用。 顺序IO&#xff08;Sequen…

TeamViewer关闭访问密码或固定一组密码不变

TeamViewer的新UI界面变化较大&#xff0c;网上的一些信息已经不再有效&#xff0c;更新后的访问密码在如下图所示&#xff1a; 演示的版本为7.21.4—— 设置每次你的设备访问的密码

Hi6274 反激式20瓦电源芯片

HI6274为高性能多模式 PWM 反激式20瓦电源芯片。HI6274较少的外围元器件、较低的系统成本可设计出高性能的"无Y"开关电源。HI6274提供了极为全面和性能优异的智能化保护功能&#xff0c;包括逐周期过流保护、过载保护、软启动、芯片过温保护、可编程输出过压保护功能…

Kettle 登录示例 POST请求

登录接口是post请求&#xff0c;组装Body为json字符串 var body "{\"username\":\""username"\",\"password\": \""password"\",\"code\":\""verification"\",\"uuid\…

【算法/训练】:前缀和差分

&#x1f680; 前言&#xff1a; 前面我们已经通过 【算法/学习】前缀和&&差分-CSDN博客 学习了前缀和&&差分的效相关知识&#xff0c;现在我们开始进行相关题目的练习吧 1. 校门外的树 思路&#xff1a;给[0, n]的数组都标记为1&#xff0c;然后输出m行范围…

初学Mybatis之配置解析

MyBatis 中文网配置教程 mybatis-config.xml 环境配置&#xff08;environments&#xff09; 尽管可以配置多个环境&#xff0c;但每个 SqlSessionFactory 实例只能选择一种环境 可以有多个 enviroment&#xff0c;但是 enviroments default&#xff08;默认&#xff09;只…

Linux:Linux发展史

大家好&#xff01;此篇文章并非技术博文&#xff0c;而是简单了解Linux的时代背景和发展史&#xff0c;只有知其所以然才能让我们更好地让走进Liunx的世界&#xff01; 一、计算机的发展历史背景 首先我们要知道&#xff0c;早期大多数科技的进步都是以国家的对抗为历史背景的…

【优秀设计案例】基于K-Means聚类算法的球员数据聚类分析设计与实现

背景及意义 随着NBA比赛的日益竞争激烈&#xff0c;球队需要更加深入地了解球员的能力和特征&#xff0c;以制定更有效的战术和球队管理策略。而NBA球员的统计数据包含了大量有价值的信息&#xff0c;通过对这些数据进行聚类分析&#xff0c;可以揭示出球员之间的相似性和差异…

Java生成四位纯数字并且确保唯一性

背景&#xff1a; 给了我一个需求&#xff0c;由于某些问题原因&#xff0c;需要给属性和数据添加一个code字段&#xff0c;这是给我发的消息 这两个要求其实是同一个需求&#xff0c;就是在创建对象的时候塞入一个unique的code嘛&#xff0c;听起来很简单吧&#xff0c;但是实…