自学内容网 自学内容网

探索 Java 中的 DeferredResult<Object>

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

  • 专栏导航:

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

探索 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> 可以大大提升系统的性能和用户体验。希望本文能够帮助您更好地理解和应用这一工具,为您的项目带来更多的价值。


原文地址:https://blog.csdn.net/weixin_44976692/article/details/140619973

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!