使用Spring 3.2的DeferredResult进行长轮询

在我们的最后一集中 , Agile Cowboys Inc.的首席执行官刚刚雇用了Java / Spring顾问,方法是为他提供最初为女友购买的保时捷。 这位首席执行官的女友因失去保时捷而感到不安,已将其婚外情告诉了他的妻子。 他的妻子在分拆了CEO的套房后已申请离婚。 同时,首席执行官在办公室实施了新的“休闲”着装要求,而Java / Spring顾问刚从他的保时捷换乘回来,正坐在办公桌旁准备修理电视公司的软件……如果不这样做的话对您没有任何意义,然后看一下使用Spring的Long Polling Tomcat 。

Java / Spring顾问必须在下一个大型游戏之前解决电视公司的服务器资源问题,他知道他可以通过使用在Tomcat 7 1上实现的Servlet 3规范实现Spring的Deferred Result技术来解决此问题。

Java / Spring顾问要做的第一件事是检查 项目的pom.xml文件。 对于异步Servlet 3项目,必须包括以下依赖项:

<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.0.1</version><scope>provided</scope></dependency>

接下来,您必须告诉Tomcat Spring DispatcherServlet支持Servlet 3异步通信。 这是通过将以下行添加到web.xml

<async-supported>true</async-supported>

完整的DispatcherServlet配置为:

<servlet><servlet-name>appServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value></init-param><load-on-startup>1</load-on-startup><async-supported>true</async-supported></servlet>

整理完项目配置后,Java / Spring ConsultantSwift进入了控制器代码。 他用新的DeferredMatchUpdateController代替了研究生培训生的SimpleMatchUpdateController

@Controller() 
public class DeferredMatchUpdateController { @Autowired private DeferredResultService updateService; @RequestMapping(value = "/matchupdate/begin" + "", method = RequestMethod.GET) @ResponseBody public String start() { updateService.subscribe(); return "OK"; } @RequestMapping("/matchupdate/deferred") @ResponseBody public DeferredResult<Message> getUpdate() { final DeferredResult<Message> result = new DeferredResult<Message>(); updateService.getUpdate(result); return result; } 
}

新的DeferredMatchUpdateController非常简单。 与SimpleMatchUpdateController一样,它包含两个方法: start()getUpdate() ,它们的功能与简单方法完全相同。 这使该控制器成为SimpleMatchUpdateController的插件替代品。 最大的不同是, getUpdate()方法创建Spring的DeferredResult的实例,该实例在将其返回给Spring之前将其传递给新的DeferredResultService 。 然后Spring停放HTTP请求,使其挂起,直到DeferredResult对象具有一些要返回到浏览器的数据为止。

@Service("DeferredService") 
public class DeferredResultService implements Runnable { private static final Logger logger = LoggerFactory.getLogger(DeferredResultService.class); private final BlockingQueue<DeferredResult<Message>> resultQueue = new LinkedBlockingQueue<>(); private Thread thread; private volatile boolean start = true; @Autowired @Qualifier("theQueue") private LinkedBlockingQueue<Message> queue; @Autowired @Qualifier("BillSkyes") private MatchReporter matchReporter; public void subscribe() { logger.info("Starting server"); matchReporter.start(); startThread(); } private void startThread() { if (start) { synchronized (this) { if (start) { start = false; thread = new Thread(this, "Studio Teletype"); thread.start(); } } } } @Override public void run() { while (true) { try { DeferredResult<Message> result = resultQueue.take(); Message message = queue.take(); result.setResult(message); } catch (InterruptedException e) { throw new UpdateException("Cannot get latest update. " + e.getMessage(), e); } } } public void getUpdate(DeferredResult<Message> result) { resultQueue.add(result); } }

同样,像其对应的SimpleMatchUpdateServiceDeferredResultService包含两个方法: subscribe()getUpdate()

与处理getUpdate(...)它的作用是为新创建的添加DeferredResult对象到LinkedBlockingQueueresultQueue ,以便它可以在以后当比赛更新可用来处理。

实际工作是通过subscribe()方法完成的。 首先,此方法启动matchReporter ,它在适当的时候将匹配更新输入到自动装配的queue实例中。 然后,它调用私有的startThread()方法来启动工作线程。 该操作仅启动一次,并使用双重检查锁定来确保高效且没有问题。

线程的run()方法首先无限循环,从resultQueue (如果有)中获取DeferredResult对象,然后是Message对象,该对象代表来自update queue的匹配更新(如果有)。 然后,使用message对象作为参数调用DeferredResultsetResult(...) 。 Spring现在将接管工作,原始的长轮询请求将完成,并且数据将延迟地返回给浏览器。

请注意,在此示例代码中, run()方法包含while(true)循环。 尽管此技术简化了示例代码,但在生产代码方面并不是一个好主意。 使用任性的不受控制的线程的问题之一是它们会阻止Tomcat正确关闭,并且您通常必须使用良好的Unix kill命令来停止服务器。 在生产代码中,最好包含代码以正常关闭此类工作线程。

经过数小时的辛苦工作,Java / Spring顾问将其代码推广到生活中,拿起保时捷的钥匙,然后旋转一下。 下个星期六,使用Spring的DeferredResult ,服务器可以很好地应对:用户很高兴,电视公司的总裁很高兴, Agile Cowboys Inc的首席执行官很高兴,尽管他一直怀疑自己付给顾问的钱太多了,嘿,这只是钱。

1在撰写此博客时,我使用的是Tomcat 7.0.42版

该博客随附的代码可在Github上找到: https : //github.com/roghughe/captaindebug/tree/master/long-poll

参考: Captain Debug博客博客中来自JCG合作伙伴 Roger Hughes的Spring 3.2的DeferredResult长轮询 。

翻译自: https://www.javacodegeeks.com/2013/09/long-polling-with-spring-3-2s-deferredresult.html

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

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

相关文章

移动spa商城优化记(一)---首屏优化篇

背景 随着公司业务的不断壮大&#xff0c;最近老是有用户反应公司APP内的商城打开比较慢&#xff0c;这可不行啊&#xff0c;慢了容易流失用户&#xff0c;流失用户减少公司业绩&#xff0c;公司业绩少我的年终奖就少…………&#xff0c;所以为了公司&#xff0c;也为了自己&a…

hprose for java 教程_hprose for java源码分析-4

4.1 疑窦丛生书接上回。上回说到&#xff0c;从HproseClient.java ------------------------- (#0)invokeHandler.handle()开始&#xff0c;将经历一个漫长的调用过程&#xff0c;下面把整个调用链粘出来&#xff0c;先认识下这个庞然大物。( >>> 表示调用到&#xff…

Git可视化极简易教程 — Git GUI使用方法

Git可视化极简易教程 — Git GUI使用方法 学习了&#xff1a;http://www.runoob.com/w3cnote/git-gui-window.html转载于:https://www.cnblogs.com/stono/p/9026292.html

如何用堆栈来保存和恢复滚动条位置

问题背景 在单页应用中&#xff0c;翻页一般通过display:none将先前的面板&#xff08;一般就是个div容器&#xff09;隐藏&#xff0c;然后将本次需要展现的面板设置成display:block&#xff08;当然&#xff0c;还可能加点css切换动画&#xff0c;不过不影响我们本次的讨论结…

如何在Hibernate中维护表的历史记录

为了维护数据库的历史记录或跟踪数据库表行的修改&#xff0c;我们创建了一个版本表&#xff0c;其中包含与原始表相同的字段。每当原始表被更改时&#xff0c;我们都会在版本表中创建另一个条目。 因此&#xff0c;对于每个更新查询&#xff0c;我们都必须在版本表中编写一个插…

java批量提取文件夹名称_bat 批量提取指定目录下的文件名

bat 批量提取指定目录下的文件名下面是批量获取指定目录下的文件名的核心代码echo offecho text inputset inputset /p input:echo %input% is inputcd %input%rem echo onfor %%a in (*) do (echo %%a is input)cd ..如下是sql server执行对应脚本文件sqlcmd -Spcserver -dmas…

埃及分数The Rotation Game骑士精神——IDA*

IDA*&#xff1a;非常好用的搜索&#xff0c;可以解决很多深度浅&#xff0c;但是规模大的搜索问题。 估价函数设计思路&#xff1a;观察一步最多能向答案靠近多少。 埃及分数 题目大意&#xff1a; 给出一个分数&#xff0c;由分子a 和分母b 构成&#xff0c;现在要你分解成一…

[UE4]创建Shooter基类,2种方法

一、可以通过直接修改"BP_FPPCharacter"的名字为“BP_Shooter”作为基类&#xff0c;然后新建一个"BP_FPPCharacter"继承自“BP_Shooter”。 这种方法适用于各个类对"BP_FPPCharacter"依赖不多的情况。 二、创建一个“BP_Shooter”继承于“Chara…

美团扫码付的前端可用性保障实践

开篇 2017年&#xff0c;美团金融前端遇到了很多通用性问题&#xff0c;特别是在保障前端可用性的过程中&#xff0c;我们团队也踩了不少“坑”&#xff0c;在梳理完这些问题以后&#xff0c;我们还专门做了第31期线下沙龙给大家进行了分享。不管是在面试过程中与候选人讨论&a…

Servlet上传文件和下载文件示例

Java Web应用程序中的文件上载和下载以及常见任务。 由于最近我写了很多有关Java servlet的文章 &#xff0c;因此我想提供一个使用servlet上传和下载文件的示例示例。 用例 我们的用例是提供一个简单HTML页面&#xff0c;客户端可以在其中选择要上传到服务器的本地文件。 在提…

用java单源最短路径问题_单源最短路径-贪心算法

单源最短路径&#xff0c;关于这个问题的贪心算有点不好理解&#xff0c;分析后续补充&#xff0c;代码也需要后续优化&#xff0c;便于理解package test;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;/*** Created by sa…

APPLE STORE

直接在设置中&#xff0c;使用查看APPLE ID是无法更改的&#xff0c;现在必须要有所在区域的信用卡信息&#xff0c;支付方式无法像以前一样选择“无”。 查询后发现&#xff0c;有人说icloud3.0,即这个旧版的可以进行更改&#xff0c;于是下载。 但发现一个问题&#xff0c;输…

vue项目打包后文本溢出代码消失问题

补充 https://www.cnblogs.com/richard1015/p/8526988.html vue webpack 打包编译-webkit-box-orient: vertical 后消失 解决方案 optimize-css-assets-webpack-plugin这个插件的问题 注释掉webpack.prod.conf.js中下面的代码 new OptimizeCSSPlugin({cssProcessorOptions: c…

前端图片canvas,file,blob,DataURL等格式转换

最近用到一些图片相关的操作&#xff0c;记录一下笔记。 将file转化成base64 场景&#xff1a; 获取到一个file类型的图片&#xff0c;如果直接在html中预览&#xff1f;这里就是利用html5的新特性&#xff0c;将图片转换为Base64的形式显示出来。有两种方法&#xff1a; 方法…

java创建异步多线程_Java创建多线程异步执行实现代码解析

实现Runable接口通过实现Runable接口中的run()方法public class ThreadTest implements Runnable {public static void main(String[] args) {Thread thread new Thread(new ThreadTest());thread.start();}Overridepublic void run() {System.out.println("Runable 方式…

Java中的状态设计模式–示例教程

状态模式是行为设计模式之一 。 当对象根据其内部状态更改其行为时&#xff0c;将使用状态设计模式。 如果必须根据对象的状态更改其行为&#xff0c;则可以在对象中使用状态变量&#xff0c;并使用if-else条件块根据状态执行不同的操作。 状态模式用于通过上下文和状态实现提…

JS 循环遍历 总结

一、循环遍历语句 for...in... &#xff08;ES5&#xff09; 语法&#xff1a;javascript for(keys in obj){}适用&#xff1a;遍历对象说明&#xff1a;   1.keys表示obj对象的每一个键值对的键(键名)&#xff0c;所有循环中&#xff0c;需要使用obj[keys]来取到每一个值。 …

java之平台无关

java虚拟机是执行字节码文件&#xff08;.class&#xff09;的虚拟机进程。 java源程序&#xff08;.java&#xff09;被编译器编译成------>字节码文件&#xff08;.class&#xff09;,然后字节码文件&#xff0c;将由java虚拟机&#xff0c;解释成------>机器码&#x…

适用于ActiveMQ 5.9的Apache Camel Broker组件

将Apache Camel嵌入ActiveMQ代理可以为使用Camel的集成功能扩展消息代理提供极大的灵活性。 Apache Camel路由的另一个好处是&#xff0c;如果使用activemq组件 &#xff0c;则可以避免远程连接到ActiveMQ的序列化和网络开销。 关于Apache ActiveMQ真正伟大的事情之一是&#x…

java rpg对战_RpgGame.java

import java.util.Scanner;public class RpgGame {public static void main(String[] args) {System.out.println("--------------------亲爱的勇士欢迎来到文字世界--------------------");System.out.println("--------------------这是一个充斥着危险的世界&…