返回顶部
首页 > 资讯 > 后端开发 > Python >Java 利用DeferredResult实现http轮询实时返回数据接口
  • 237
分享到

Java 利用DeferredResult实现http轮询实时返回数据接口

2024-04-02 19:04:59 237人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

目录1. 消息返回实体类,大家可以根据实际情况,自己定义即可:2. controller 接口:3. service 实现:今天这篇文章呢,不难,其实是解答我一直以来心里的一个疑问。

今天这篇文章呢,不难,其实是解答我一直以来心里的一个疑问。是这样的,之前看五八技术委员会主席沈剑老师的公众号架构师之路的一篇文章:Http 如何像 tcp 一样实时的收消息,里面其中的一个方案是用 http 短连接轮询的方式实现“伪长连接”。但是对于轮询,我们的第一反应肯定是有延时,但是标题不是说的是实时吗?当然我们可以把轮询的时长缩短一些,先不说这样大部分时间的轮询调用,可能都没消息返回,造成服务器资源浪费,轮询时间再短也是有延时啊,所以难道是伪实时?反正一般消息延时个三五秒,甚至十秒八秒一分钟,大家也不会在意,只会认为对方返回慢,对不起,这是我们程序员的锅,但是 http 真的不能实现实时吗?沈剑老师提出了一种方法:首选 WEBim 和 webserver 之间建立一条 http 连接,专门用作消息通道,这条连接叫 http 消息连接。然后会有如下处理:

1. 没有消息到达的时候,这个 http 消息连接将被夯住,不返回,由于 http 是短连接,这个 http 消息连接最多被夯住 90 秒,就会被断开(这是浏览器或者 webserver 的行为);

2. 在 1 的情况下,如果 http 消息连接被断开,立马再发起一个 http 消息连接;

此时在在 1 和 2 的配合下,浏览器与 webserver 之间将永远有一条消息连接在,然后还有一种情况

3. 每次收到消息时,这个消息连接就能及时将消息带回浏览器页面,并且在返回后,会立马再发起一个 http 消息连接

这样就能做到使用 http 端连接轮询的方式实现了实时收消息。不过需要说明的是,其实还有一种情况:消息到达时,上一个 http 消息连接正在返回,也就是第二种情况的时候突然来了一个消息,此时没有 http 消息连接可用。虽然理论上 http 消息连接的返回是瞬时的,没有消息连接可用出现的概率极小,但是根据墨菲定律我们知道,这种情况肯定会出现,所以这种情况下我们可以将消息暂存入消息池中,下一个消息连接到达后,无需等待,直接去消息池中取消息,将将消息带回,然后立刻返回生成新的消息连接即可。

不过以上都不是今天这篇文章的重点,和今天这篇文章的标题也没有任何关系。重点是当时看了沈剑老师的这篇文章后我一直有一个疑问:第一步的时候如何夯住?总不能 sleep 吧,这多不优雅啊,由于一直以为没有遇到过类似的需求,所以这么几年来我也没深究这个问题,但是心里确实一直记着,直到前一段时间,听马士兵教育的公开课,当时再讲类似的问题的时候提到了夯住 http 的连接(具体是哪个问题,还真不记得了),虽然当时上课的老师没提怎么实现,但是评论区我问了一下,如何夯住不返回?然后有一个同学回复说,用 DeferredResult,然后下课后搜了一下资料,果然可以,如下是实现的笔记,所以这才是重点,希望对有这个疑问的同学也有一点帮助。

1. 消息返回实体类,大家可以根据实际情况,自己定义即可:


package cn.bridgeli.deferredresulttest.entity;
 
import lombok.Data;
import lombok.Getter;
 

@Data
public class DeferredResultResponse {
    private Integer code;
    private String msg;
 
    public enum Msg {
        TIMEOUT("超时"),
        FaiLED("失败"),
        SUCCESS("成功");
 
        @Getter
        private String desc;
 
        Msg(String desc) {
            this.desc = desc;
        }
    }
}

2. controller 接口:


package cn.bridgeli.deferredresulttest.controller;
 
import cn.bridgeli.deferredresulttest.entity.DeferredResultResponse;
import cn.bridgeli.deferredresulttest.service.DeferredResultService;
import org.springframework.http.httpstatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
 
import javax.annotation.Resource;
 
 

@RestController
@RequestMapping(value = "/deferred-result")
public class DeferredResultController {
 
    @Resource
    private DeferredResultService deferredResultService;
 
    
    private final String requestId = "test";
 
 
    @GetMapping(value = "/get")
    public DeferredResult<DeferredResultResponse> get(@RequestParam(value = "timeout", required = false, defaultValue = "10000") Long timeout) {
        DeferredResult<DeferredResultResponse> deferredResult = new DeferredResult<>(timeout);
 
        deferredResultService.process(requestId, deferredResult);
 
        return deferredResult;
    }
 
    
    @GetMapping(value = "/result")
    public String settingResult(@RequestParam(value = "desired", required = false, defaultValue = "成功") String desired) {
        DeferredResultResponse deferredResultResponse = new DeferredResultResponse();
        if (DeferredResultResponse.Msg.SUCCESS.getDesc().equals(desired)) {
            deferredResultResponse.setCode(HttpStatus.OK.value());
            deferredResultResponse.setMsg(desired);
        } else {
            deferredResultResponse.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
            deferredResultResponse.setMsg(DeferredResultResponse.Msg.FAILED.getDesc());
        }
        deferredResultService.settingResult(requestId, deferredResultResponse);
 
        return "Done";
    }
}

其中:/get 接口模拟沈剑老师说的消息连接,/result 接口模拟有一条新消息来了,然后 /get 接口会立即返回。主要注意的是 requestId,在实际项目中不能使用同一个,否则会出现问题,这个测一下就知道了,也很容易想到原因。

3. service 实现:


package cn.bridgeli.deferredresulttest.service;
 
import cn.bridgeli.deferredresulttest.entity.DeferredResultResponse;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.async.DeferredResult;
 
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
 

@Service
public class DeferredResultService {
 
    private Map<String, Consumer<DeferredResultResponse>> taskMap;
 
    public DeferredResultService() {
        taskMap = new ConcurrentHashMap<>();
    }
 
    
    public void process(String requestId, DeferredResult<DeferredResultResponse> deferredResult) {
        // 请求超时的回调函数
        deferredResult.onTimeout(() -> {
            taskMap.remove(requestId);
            DeferredResultResponse deferredResultResponse = new DeferredResultResponse();
            deferredResultResponse.setCode(HttpStatus.REQUEST_TIMEOUT.value());
            deferredResultResponse.setMsg(DeferredResultResponse.Msg.TIMEOUT.getDesc());
            deferredResult.setResult(deferredResultResponse);
        });
 
        Optional.ofNullable(taskMap)
                .filter(t -> !t.containsKey(requestId))
                .orElseThrow(() -> new IllegalArgumentException(String.fORMat("requestId=%s is existing", requestId)));
 
        taskMap.putIfAbsent(requestId, deferredResult::setResult);
    }
 
    
    public void settingResult(String requestId, DeferredResultResponse deferredResultResponse) {
        if (taskMap.containsKey(requestId)) {
            Consumer<DeferredResultResponse> deferredResultResponseConsumer = taskMap.get(requestId);
            // 这里相当于DeferredResult对象的setResult方法
            deferredResultResponseConsumer.accept(deferredResultResponse);
            taskMap.remove(requestId);
        }
    }
 
}

文章最后,我想在说明另外一个问题,我们利用 DeferredResult 实现了 http 轮询返回,其实换个思路想问题,我们是不是也实现了 http 接口延时返回?所以如果你有延时返回的需求,同样可以借助 DeferredResult 实现。

以上就是Java 利用 DeferredResult 实现 http 轮询实时返回数据接口的详细内容,更多关于Java 实现 http 轮询实时返回数据接口的资料请关注编程网其它相关文章!

--结束END--

本文标题: Java 利用DeferredResult实现http轮询实时返回数据接口

本文链接: https://lsjlt.com/news/122648.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Java 利用DeferredResult实现http轮询实时返回数据接口
    目录1. 消息返回实体类,大家可以根据实际情况,自己定义即可:2. controller 接口:3. service 实现:今天这篇文章呢,不难,其实是解答我一直以来心里的一个疑问。...
    99+
    2024-04-02
  • Java实现调用对方http接口得到返回数据
    目录Java用对方http接口得到返回数据java后台工具类调用api接口,解析数据一、引入jar包二、httpclient请求接口工具类Java 用对方http接口得到返回数据 如...
    99+
    2024-04-02
  • golang接口返回空数组怎么实现
    在Go语言中,可以使用nil来表示空数组。具体实现如下:```gopackage mainimport ("fmt")type My...
    99+
    2023-09-27
    golang
  • Django 查询数据库返回JSON的实现
    目录返回多条数据返回单个对象和前端交互全部使用JSON,如何将数据库查询结果转换成JSON格式 返回多条数据 示例 import json from django.http i...
    99+
    2024-04-02
  • node.js+Ajax实现获取HTTP服务器返回数据
    我们看一个HTML5页面中通过AJAX请求的方式获取HTTP服务器返回数据的代码示例.由于我们把服务器的端口指定为1337,并将从端口为80的网站中运行HTML5页面,因此这是一种跨域操作,需要在HTTP响...
    99+
    2022-06-04
    服务器 数据 js
  • Django如何实现查询数据库返回JSON
    这篇文章给大家分享的是有关Django如何实现查询数据库返回JSON的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。返回多条数据示例import jsonfrom django.http&nbs...
    99+
    2023-06-20
  • SpringMVC中的json数据怎么利用controller实现返回
    这期内容当中小编将会给大家带来有关SpringMVC中的json数据怎么利用controller实现返回,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1.jsp的ajax请求:function getJs...
    99+
    2023-05-31
    springmvc controller json
  • Java接口返回省市区树形结构的实现
    目录前言设计表结构Java代码调用接口查看结果前言 最近和前端联调接口,需要进行一个省市区联动,最终定的方案是通过接口返回一个树形结构给前端,类似这样的结构: 下面就把相关表和代码...
    99+
    2023-01-08
    Java 返回树形结构 Java 接口返回树形结构
  • 如何利用 Python 接口处理大数据并实现实时分析?
    随着互联网和物联网的快速发展,大数据的处理与分析已成为各行各业不可或缺的一环。Python 作为一种强大的编程语言,拥有丰富的第三方库和模块,可以轻松地处理大量数据,并实现实时分析。本文将介绍如何利用 Python 接口处理大数据并实现实时...
    99+
    2023-07-28
    接口 大数据 实时
  • springMVC利用FastJson接口返回json数据相关配置详解
    一直使用的是FastJson,感觉还不错,很方便。看了一段别人的分析,觉得很有道理。为什么要使用Fastjson,其实原因不需要太多,喜欢就行。 我之所以要替换掉Jackson最主要的原因是Jackson在处理对象之前的循环嵌套关系时不便。...
    99+
    2023-05-31
    springmvc fastjson
  • 怎么实现OpenAPI开发动态处理接口的返回数据
    这篇文章主要介绍“怎么实现OpenAPI开发动态处理接口的返回数据”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么实现OpenAPI开发动态处理接口的返回数据”文章能帮助大家解决问题。0 | 需求...
    99+
    2023-07-06
  • springBoot之如何获取接口请求数据和返回数据实现日志
    目录一、获取接口请求的数据HttpServletRequestFilterRequestWrapperafterCompletion二、获取接口返回的数据HttpServletRes...
    99+
    2023-05-14
    springBoot接口 springBoot接口请求数据 springBoot返回数据日志
  • springBoot之怎么获取接口请求数据和返回数据实现日志
    这篇文章主要介绍“springBoot之怎么获取接口请求数据和返回数据实现日志”,在日常操作中,相信很多人在springBoot之怎么获取接口请求数据和返回数据实现日志问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家...
    99+
    2023-07-05
  • Java接口返回省市区树形结构如何实现
    这篇文章主要介绍“Java接口返回省市区树形结构如何实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java接口返回省市区树形结构如何实现”文章能帮助大家解决问题。前言最近和前端联调接口,需要进行...
    99+
    2023-07-04
  • 如何利用ASP接口实现大数据索引的快速查询?
    如何利用ASP接口实现大数据索引的快速查询? 随着大数据时代的到来,数据量的增长使得数据的查询变得越来越复杂和困难。这时候,我们需要一种快速高效的数据查询方式,这就是利用ASP接口实现大数据索引的快速查询。本文将会介绍如何利用ASP接口实现...
    99+
    2023-10-04
    接口 大数据 索引
  • 如何使用Java数组处理实时接口数据?
    在现代软件开发中,实时接口数据处理已经成为了一个非常重要的部分。而在Java开发中,数组是处理数据的重要工具之一。因此,在本文中,我们将讨论如何使用Java数组处理实时接口数据。 一、什么是实时接口数据? 实时接口数据是指从外部设备或系统...
    99+
    2023-06-06
    实时 接口 数组
  • python怎么实现接口测试返回数据为字典取值方式
    本文小编为大家详细介绍“python怎么实现接口测试返回数据为字典取值方式”,内容详细,步骤清晰,细节处理妥当,希望这篇“python怎么实现接口测试返回数据为字典取值方式”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知...
    99+
    2023-06-29
  • 详解如何实现OpenAPI开发动态处理接口的返回数据
    目录0 | 需求说明1 | 思路方案2 | 具体实施0 | 需求说明 业务场景:服务A对接了服务B,服务C等服务的一些接口,然后由服务A统一暴露接口给到外部用户使用。 需求是: 服...
    99+
    2023-05-15
    OpenAPI动态处理接口返回数据 OpenAPI 接口返回处理
  • 利用Java怎么实现面向接口编程
    利用Java怎么实现面向接口编程?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1.面向接口编程和面向对象编程是什么关系首先,面向接口编程和面向对象编程并不是平级的,它并不是...
    99+
    2023-05-31
    java ava
  • java利用webService 如何实现一个WSDL接口
    java利用webService 如何实现一个WSDL接口?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。一、使用JDK生成WSDL的对象类cmd进入JDK的bin文件中  ...
    99+
    2023-05-31
    java wsdl webservice
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作