如何将数据推送到jsp而不每2秒请求一次?
Posted
技术标签:
【中文标题】如何将数据推送到jsp而不每2秒请求一次?【英文标题】:how to push the data to the jsp with out requesting it for every 2 seconds? 【发布时间】:2012-01-27 16:02:06 【问题描述】:我想每 2 秒将数据推送到 jsp,而不需要客户端请求。 我在这里使用 Spring 和 Hibernate。 我正在显示谷歌地图标记,我想通过从数据库中获取数据每 2 秒更新一次标记位置,但是我已经完成了每 2 秒从数据库中获取数据,但我无法将该数据推送到此jsp.
@Scheduled(fixedRate = 2000)
public void getData()
// TODO Auto-generated method stub
DeviceDetails deviceDetails = realTimeDataDAO.getDeviceDetails(deviceId);
System.out.println(deviceDetails);
我必须每 2 秒显示一些数据。谁能告诉我该怎么做?
有人知道CometAjax Push 技术,在这种情况下能用吗?
【问题讨论】:
刚刚回答 - 如果您说出您正在使用的应用服务器 - 或者您可以灵活选择哪个应用服务器,将会很有帮助。 【参考方案1】:你有很多选择。
轮询 - 如其他答案中所述,您可以简单地让客户端中的 javascript 每 2 秒不断轮询服务器。这是一种非常常见的方法,很简单,适用于大多数浏览器。虽然不像其他一些正确设置的方法那样可扩展,但它仍然应该能够轻松扩展到中等容量(可能比您拥有的用户更多!)。
长期轮询 - 也称为 Comet,这本质上是一个长期存在的请求。这将根据您的应用服务器而有所不同。有关 Tomcat,请参见此处:http://wiki.apache.org/tomcat/WhatIsComet 或 Jetty 捆绑了一些示例。
HTML 5 解决方案 虽然 Web 传统上是基于请求响应的 - 基于事件的处理是 html 5 规范的一部分。由于您的事件似乎只是一种方式(服务器-> 客户端),请考虑使用事件源。请参阅:http://www.html5rocks.com/en/tutorials/eventsource/basics/ 或 Jetty 示例。这里需要注意的是,只有现代浏览器和一些应用服务器支持这些方法——例如Apache 本身并不支持 websocket。
总结一下 - 我的直觉是您的需求和简单的轮询方法很好 - 最初不要太担心性能问题。
如果您想走在最前沿,学习新事物并且可以控制您的应用服务器和框架,那么我会选择 HTML 5 方法。
彗星是这两者之间的中途之家。
【讨论】:
嗨,Pablojim,我正在使用 Tomcat 作为带有 spring + hibernate + google maps api v3 的服务器。我对 HTML 5 没有任何了解,你能指导我吗?【参考方案2】:使用 Spring 的最佳选择是将预定查询的结果存储到内存中的 bean 中,然后让另一个请求范围 bean 以可 Web 访问的方法获取存储的结果,并将其作为文本(或 JSON )。或者,您可以在每次请求更新时查询数据库。
然后,您可以从您的页面发出定时异步请求(您可能希望为此使用 YUI 连接管理器),读取响应并使用 google.maps.Map 中的 panTo 方法更新您的地图位置。
如您所见,解决方案分为 Java 和 JavaScript 部分。
对于 Java 端,您必须创建一个控制器来执行对数据库的查询(或者更好的是,将该任务委托给另一层)并以 JSON 格式返回结果,您可以为此使用http://spring-json.sourceforge.net/。它在 Spring 中有点复杂,因此您可能希望创建一个返回数据的简单 servlet。
对于 Javascript 端,一旦你有一个返回 JSON 数据的工作端点,使用 YUI Connection Manager 和 google maps api:
function update()
var callback =
success: function (o)
var response = YAHOO.lang.JSON.parse(o.responseText);
map.panTo(lat: response.lat, lng: response.longi); // map is the google.maps.Map representing your map
,
failure: function (o)
var sUrl = '/getData.htm'; // This is the request mapping for your bean
YAHOO.util.Connect.asyncRequest('GET', sUrl,callback);
function init()
setTimeout("update()", 2000);
【讨论】:
非常感谢@Slash,但是除了 YUI 还有其他方法吗,因为我对此一无所知。 @RameshK 你了解 JavaScript 框架吗?因为我认为你不能单独使用 Spring 来做到这一点; Spring 是服务器端,因此您可以安排要执行的任务,但据我所知,这些只会发生在服务器上。例如,此代码使用 JQuery 而不是 YUI:blog.springsource.org/2010/01/25/… 我建议你试试 YUI 解决方案,它很容易设置(只需将 yui js 文件添加到您的页面,或直接从雅虎网站加载它们:developer.yahoo.com/yui/articles/hosting/…。然后你可以使用 YAHOO.util.connect 函数【参考方案3】:最好的方法是让客户端每 2 秒发送一次 new 请求,然后显示新数据。
由于您使用 HTTP,我假设您在客户端使用 javascript,因此您的 javascript 中需要一个计时器,每 2 秒触发一次,然后让 javascript 对服务器执行 ajax 调用以获取它可以获取的数据然后显示。
【讨论】:
【参考方案4】:尝试TimerTask 或ThreadExecutor(查看计划的实施)。
【讨论】:
java2s.com/Code/Java/Development-Class/… 我不认为这真的有帮助,因为它没有解决向用户显示数据的问题【参考方案5】:好吧,如果您想在 Web 应用程序中实现上述解决方案,我不确定,但我认为您不能这样做。 HTTP 是一种请求/响应协议,当服务器完成发送一个响应时,它不能自行发起发送新响应。简而言之:来自客户端的一个请求 - 来自服务器的一个响应。
我认为您应该使用 AJAX(异步 Javascript 请求),以便每 2 秒向服务器询问一次新数据,并在必要时更新 DOM(网站 HTML 标记结构)。
【讨论】:
我认为通过 ajax 发送请求不是好方法,因为每次我们都需要访问同一个数据库表。因此,如果我们编写一个运行后台的 Java 守护线程并将数据连续发送到 UI。 这可能看起来是个坏主意,但它是 Web 应用程序中的常见解决方案 :) @M.Hryszczyk 你可能在十年前是正确的。 HTTP 的原始规范正如您所说,但它的流行和对推送功能的共同要求导致几乎每个服务器平台上都有 数十 种类似彗星的服务器推送流实现。 Server-Sent-Events 和 Web Sockets 只会继续这种演变,它们都经过巧妙设计,可以在 http/port 80 上共存。【参考方案6】:我对 WebSockets 有很好的经验。服务器和浏览器之间非常快速、低开销的双向协议。不确定您的后端是什么,但 Jetty 非常支持它。只需在后端有一个计时器进程,它将遍历所有活动的 WebSockets 会话并推送更新。网上有很多关于如何使用 Websockets 的例子。
注意事项:
并非所有浏览器都支持 WebSockets(Chrome 和 Safari 似乎是最受支持的) WebSockets 流量不会遍历所有代理根据您的要求,它可能会或可能不会被接受。
有一些像 Atmosphere 这样的项目试图抽象浏览器/服务器在 websockets 支持方面的差异,并优雅地回退到 Comet。可能值得一看。
【讨论】:
【参考方案7】://Initialize this somewhere
ScheduledExecutorService exe = Executors.newScheduledThreadPool(1);
exe.scheduleWithFixedDelay(new Runnable()
@Override
public void run()
//The executor service tries to run 2 seconds after it last finished
//If you code takes 1 second to run this will effectively run every 3 seconds
, 0, //this is the initial delay
2, //this is the consecutive delay
TimeUnit.SECONDS);
exe.scheduleAtFixedRate(new Runnable()
@Override
public void run()
//The executor service tries to run this every 2 seconds
//If you code takes 1 second to run this will still run evey 2 seconds
, 0, //this is the initial delay
2, //this is the period it tries to run in
TimeUnit.SECONDS);
【讨论】:
谢谢老兄,你能告诉我如何更新jsp页面吗?每 2 秒运行一次此方法后,我必须获取数据并推送到 jsp ajax 和 commet 应该可以工作。您必须找到或编写一个 Java 服务器组件,然后您可以将数据推送到该组件,以及一个 JavaScript 客户端组件,该组件将在用户浏览器中“接收”数据。 最难的部分是为客户端编写自定义 JavaScript 来更新您想要的页面部分。您将无法使用任何 JSP 标记,因为它们仅在页面首次加载时进行评估。 我对 Comet 或 JavaScript 的使用还不够多,因此给您一个自定义示例感到很自在。然而,我确实发现这个例子看起来是你可以做的基础。 [链接]blogs.oracle.com/swchan/entry/a_simple_comet_example_hidden 在其中他们有一个共享计数器,任何查看网站的人都可以递增,然后每个人都会看到它。对于您的问题,您必须每 2 秒调用一次“notify()”方法,然后沿着该位置传递计数而不是传递。最后,在 java 脚本中的 updateCount() 方法中,您必须更新地图。我希望这会有所帮助。【参考方案8】:您需要每 2 秒将数据从服务器发送到客户端。而且您已经知道如何在服务器端每 2 秒收集一次数据。
如果这就是您所需要的,“Ajax 流”将为您提供帮助。这是在客户端。从服务器端每 2 秒您需要写入数据并刷新它。
搜索这个词会给你很多例子。但请记住,所有现代浏览器都将使用一种方法,所有 IE 浏览器都将使用 IFrame 方法来实现流。
在第一种情况下,您需要发出 XHR 请求并查看响应并进行处理。
这里有几个例子:(我没有时间完整地浏览它们)
http://ajaxpatterns.org/HTTP_Streaming
http://developers.cogentrts.com:8080/DH_ajax_1.asp
【讨论】:
【参考方案9】:你可以使用ajax调用。 因为您可以使用 Javascript 编写代码,每 2 秒发送一次请求,但为此,您的服务器应该对此类请求快速响应。
我想这会对你有所帮助。
【讨论】:
【参考方案10】:如果您的服务器拥有超过 1000 个用户,那么您的应用程序服务器将会失败。我建议您仅使用 Jetty 服务器支持的非阻塞输入输出方法来托管为此目的发出的请求,并将您的普通 EE 服务器用于其他应用程序。
【讨论】:
我认为这已经不正常了 @BigFatPig 不要发布您没有可靠信息来源的答案。我定期使用WebSync 在单个服务器上测试 20,000 个客户端,并让服务器集群定期同时查看 4000-6000 个真实用户。以上是关于如何将数据推送到jsp而不每2秒请求一次?的主要内容,如果未能解决你的问题,请参考以下文章
如何将数据从 asp.net 推送到 flash/silverlight 客户端?