使用DeferredResult来设计异步接口

文章目录

    • DeferredResult 介绍
    • 思路
    • Demo搭建
      • 1.定义一个抽象的请求体
      • 2.定义一个接口返回体
      • 3.定义一个接口请求体继承抽象类AsynTaskBaseRequest<T<T>>
      • 4.定义seveice类,并声明一个异步方法(Async注解)
      • 5.定义一个返回DeferredResult的接口
    • 结果验证

DeferredResult 介绍

DeferredResult 是 Spring 框架中的一种异步处理方式,它可以在处理请求时,将请求的结果暂时挂起,等待后续的处理结果再返回给客户端。这种方式可以有效地提高系统的并发处理能力,减少系统的响应时间,提高用户体验。

DeferredResult 的原理是基于 Servlet 3.0规范中的异步处理机制实现的。在 Servlet 3.0中,可以通过AsyncContext 来实现异步处理。当一个请求进入 Servlet 容器时,容器会创建一个 AsyncContext 对象,并将请求的处理交给该对象。在处理请求的过程中,如果需要进行异步处理,可以通过 AsyncContext 对象来实现。

DeferredResult是Spring框架中的一个类,用于实现异步处理和响应。它允许在处理请求时,将结果封装为一个DeferredResult对象,然后将该对象返回给客户端。这样客户端就可以继续执行其他操作,而不需要等待结果返回。 在处理请求的过程中,可以通过调用DeferredResult对象的方法setResult设置结果值。这个过程可以在任何时间点发生,甚至可以在另一个线程中。一旦结果被设置,客户端将收到响应。

tomcat 的线程池大小是有限的,在高并发场景下,如果我们的一些业务逻辑处理慢的话,会渐渐地占满 tomcat 线程,这样就无法处理新的请求,所以一些处理缓慢的业务我们会放到业务线程池中处理,但单纯的放到业务线程池中处理的话,我们无法得知其什么时候处理完,也无法将处理完的结果和之前的请求匹配上,所以常做的方式就是轮询。而 DeferredResult 的做法就类似仅把事情安排好,不会管事情做好没,tomcat 线程就释放走了,注意此时不会给请求方(如浏览器)任何响应,而是将请求存放在一边,咱先不管它,等后面有结果了再把之前的请求拿来,把值响应给请求方。

思路

我们可以借助DeferredResult 的异步处理方式,提前将请求的结果应答给客户端,再执行业务代码,类似于开了一个新的线程。当然这种只适用于客户端与服务端无强制事务关联的场景。

Demo搭建

1.定义一个抽象的请求体

import org.springframework.http.ResponseEntity;
import org.springframework.web.context.request.async.DeferredResult;public abstract class AsynTaskBaseRequest<T> {protected DeferredResult<ResponseEntity<T>> result;public abstract void makeErrorResponseMsg(int code, String message);public abstract void makeSuccessResponseMsg();protected AsynTaskBaseRequest() {this.result = new DeferredResult<>();}public DeferredResult<ResponseEntity<T>> getResult() {return result;}public void setResult(DeferredResult<ResponseEntity<T>> result) {this.result = result;}
}

2.定义一个接口返回体

import com.fasterxml.jackson.annotation.JsonProperty;public class AsynTaskBaseResponse {@JsonProperty(value = "code")private int code;@JsonProperty(value = "messages")private String messages;public AsynTaskBaseResponse() {}public AsynTaskBaseResponse(int code, String messages) {this.code = code;this.messages = messages;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMessages() {return messages;}public void setMessages(String messages) {this.messages = messages;}
}

3.定义一个接口请求体继承抽象类AsynTaskBaseRequest<T>

import com.wjw.service.common.AsynTaskBaseRequest;
import com.wjw.service.common.AsynTaskBaseResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;public class DeferredResultRequestBody extends AsynTaskBaseRequest<AsynTaskBaseResponse> {public DeferredResultRequestBody() {super();}@Overridepublic void makeErrorResponseMsg(int code, String message) {AsynTaskBaseResponse response = new AsynTaskBaseResponse(code, message);ResponseEntity<AsynTaskBaseResponse> responseEntity = new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);result.setResult(responseEntity);}@Overridepublic void makeSuccessResponseMsg() {AsynTaskBaseResponse response = new AsynTaskBaseResponse(0, "success");ResponseEntity<AsynTaskBaseResponse> responseEntity = new ResponseEntity<>(response, HttpStatus.OK);result.setResult(responseEntity);}
}

4.定义seveice类,并声明一个异步方法(Async注解)

使用@Async异步注解时首先要确认你的sprinboot项目是否开启了异步功能,检查启动类中是否加了@EnableAsync注解

在这里插入图片描述
Async 在未指定线程池时,使用的是springBoot内置的线程池,那如何指定使用自定义的线程池呢?可参考我的另一篇笔记。https://blog.csdn.net/weixin_44054222/article/details/107018400?spm=1001.2014.3001.5502

import com.wjw.service.RequestParamer.DeferredResultRequestBody;
import org.springframework.http.HttpStatus;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;@Service("DeferredResultService")
public class DeferredResultService {@Asyncpublic void demoTest(DeferredResultRequestBody requestBody){try {System.out.println("-----------接口应答前-------------");Thread.sleep(3 * 1000);requestBody.makeSuccessResponseMsg();System.out.println("-----------接口应答后-------------");Thread.sleep(10 * 1000);System.out.println("-----------执行完毕-------------");} catch (Exception e) {requestBody.makeErrorResponseMsg(HttpStatus.BAD_REQUEST.value(), e.getMessage());}}
}

5.定义一个返回DeferredResult的接口

import com.wjw.service.RequestParamer.DeferredResultRequestBody;
import com.wjw.service.common.AsynTaskBaseResponse;
import com.wjw.service.service.DeferredResultService;
import org.springframework.beans.factory.annotation.Autowired;
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;@RestController
@RequestMapping("/services/demo/v1")
public class DeferredResultController {@Autowiredprivate DeferredResultService deferredResultService;@GetMapping("/demo/test")public DeferredResult<ResponseEntity<AsynTaskBaseResponse>> test() {DeferredResultRequestBody requestBody = new DeferredResultRequestBody();deferredResultService.demoTest(requestBody);return requestBody.getResult();}
}

结果验证

这时如果调用接口控制台首先会打印"接口应答前",紧接着3s后收到接口的200 ok应答并打印”接口应答后“,等待10s打印”执行完毕“。

在这里插入图片描述

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

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

相关文章

Chrome浏览器中的vue插件devtools的下载方式(使用Chrome应用商店/科学上网情况下)

目录 devtools对前端来说的好处——开发预览、远程调试、性能调优、Bug跟踪、断点调试等 下载步骤&#xff1a; 测试阶段&#xff1a; 最近做项目要使用devtools这个vue插件。 devtools对前端来说的好处——开发预览、远程调试、性能调优、Bug跟踪、断点调试等 下载步骤…

SocketD协议单链接双向RPC模式怎么实现

SocketD是一个基于Socket的通信框架&#xff0c;支持单链接双向RPC模式。在实现单链接双向RPC模式时&#xff0c;需要按照一定的协议进行通信&#xff0c;以下是一个简单的实现示例&#xff1a; 定义通信协议&#xff1a;首先&#xff0c;需要定义客户端和服务端之间的通信协议…

【云原生】Serverless 技术架构分析

一、什么是Serverless? 1、Serverless技术简介 ​ Serverless&#xff08;无服务器架构&#xff09;指的是由开发者实现的服务端逻辑运行在无状态的计算容器中&#xff0c;它由事件触发&#xff0c; 完全被第三方管理&#xff0c;其业务层面的状态则被开发者使用的数据库和存…

基于小程序+spring boot流浪动物救助系统-计算机毕设 附源码12783

小程序spring boot流浪动物救助系统 摘 要 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;流浪动物救助系统被用…

每日一题——二叉树的遍历

题目 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序&#xff08;中序、后序&#xff09; 遍历。 数据范围&#xff1a;二叉树的节点数量满足 1≤n≤100 &#xff0c;二叉树节点的值满足 1≤val≤100 &#xff0c;树的各节点的值各不相同。 思路 二叉树的前序遍历…

C# 中使用ValueTask优化异步方法

概要 我们在开发过程中&#xff0c;经常使用async的异步方法&#xff0c;但是有些时候&#xff0c;异步的方法中&#xff0c;可能包含一些同步的处理。本文主要介绍通过ValueTask这个struct&#xff0c;优化异步处理的方法性能。 代码及实现 有些时候我们会缓存一些数据在内…

记一次Oracle归档日志异常增长问题的排查过程

Oracle归档日志是Oracle数据库的重要功能&#xff0c;用于将数据库的重做日志文件&#xff08;Redo Log&#xff09;保存到归档日志文件&#xff08;Archive Log&#xff09;中。归档日志的作用是提供数据库的备份和恢复功能&#xff0c;以及支持数据库的持续性和数据完整性。 …

Vue+Element Plus 初始化

1. 初始化 Vue 项目 创建vue3 项目 vue create k8s-platform-fe 2. 引入 Element Plus 安装 element-plus 首先去安装这些依赖包&#xff0c;安装好了将其引入&#xff0c;引入的方式有全局引用和局部引入。其实和组件是一样的&#xff0c;局部引入哪里引入哪里使用。…

接口测试和功能测试的区别

我们分成两个部分来讲&#xff1a; 第一部分&#xff1a;主要从问题出发&#xff0c;引入接口测试的相关内容并与前端测试进行简单对比&#xff0c;总结两者之前的区别与联系。但该部分只交代了怎么做和如何做&#xff1f;并没有解释为什么要做&#xff1f; 第二部分&#xf…

mac安装nvm

如果安装过node&#xff0c;须得卸载 sudo npm uninstall npm -gsudo rm -rf /usr/local/lib/node /usr/local/lib/node_modules /var/db/receipts/org.nodejs.*sudo rm -rf /usr/local/include/node /Users/$USER/.npmsudo rm /usr/local/bin/nodesudo rm /usr/local/share/m…

nginx rtmp http_flv直播推流

安装配置nginx yum install epel-release -y sudo rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm yum install ffmpeg ffmpeg-devel -y yum install gcc -y yum install pcre pcre-devel -y yum install openssl open…

Wireshark抓包分析TCP协议:三次握手和四次挥手

01、前言 面试中我们经常会被问到TCP协议的三次握手和四次挥手的过程&#xff0c;为什么总喜欢问这个问题呢&#xff1f; 其实我们平时使用的很多协议都是应用层协议&#xff0c;比如HTTP协议&#xff0c;https协议&#xff0c;DNS协议&#xff0c;FTP协议等&#xff1b;而应…

Google OAuth 2 authorization - Error: redirect_uri_mismatch 400

出现这个问题&#xff0c;一般是因为google授权origin地址和重定向redirect_uri地址没有匹配上。 请仔细检查重定向地址的url中origin部分和授权origin部分是否能够匹配&#xff1a;

kubeadm一键部署K8S流程

-架构设计&#xff1a; k8s部署&#xff1a;&#xff08;masternode1node2&#xff09; master.com:192.168.17.144 node1.com:192.168.17.146 node2.com:192.168.17.148 master上部署&#xff1a; etcd&#xff08;数据库&#xff09;、kube-apiserver、kube-controller-mana…

Android屏幕像素密度

有时需要为视图属性指定大小尺寸值&#xff08;通常以像素为单位&#xff0c;有时也用点、毫米或英寸&#xff09;。一些常见的属性包括文字大小&#xff08;text size&#xff09;、边距&#xff08;margin&#xff09;以及内边距&#xff08;padding&#xff09;。文字大小指…

美容店预约小程序制作教程详解

现在&#xff0c;制作一个专属于美容店的预约小程序不再需要编程经验&#xff0c;通过乔拓云网提供的后台管理系统&#xff0c;你可以轻松地完成整个制作过程。下面&#xff0c;我将为你详细介绍如何DIY一个美容店预约小程序。 首先&#xff0c;登录乔拓云网的后台管理系统&…

html学习5(表单)

1、表单是一个包含表单元素的区域&#xff0c;用于收集用户的输入信息。 2、表单元素是允许用户在表单中输入内容&#xff0c;比如&#xff1a;文本域&#xff08;textarea&#xff09;、下拉列表&#xff08;select&#xff09;、单选框&#xff08;radio-buttons&#xff09…

#rust taur运行报错#

场景:在window11系统上运行 tauri桌面莹应用&#xff0c;提示错误。 Visual Studio 2022 生成工具 安装的sdk11 , rust运行模式是stable-x86_64-pc-window-gnu&#xff0c; 运行npm run tauir dev 一致失败&#xff0c;失败信息如下 原因&#xff1a;1&#xff1a;在window11系…

推理加速 --- torch.compile

推理加速-- torch.compile 一、背景介绍1.2 首次推理速度慢1.3 推理多次之后&#xff0c;又会出现一次速度特别慢的情况&#xff0c;感觉好像是重新优化 二、如何使用三、其他设置3.1 mode 设置3.2 backend3.3 fullgraph3.4 dynamic 参考资料 一、背景介绍 PyTorch 2.0 官宣了…

银行网络安全体系发展及趋势思考

随着数字经济的快速发展&#xff0c;我国银行业务服务模式与技术架构发生了深刻变革。尤其在数字化转型背景下&#xff0c;网络安全作为保障银行业务稳定连续运行的基础&#xff0c;正面临更大的挑战。 银行网络安全体系与银行技术、业务架构密切相关&#xff0c;先后经历了分…