项目的原因需要实现基于Web版的网上报价查询系统。用户需求很简单就是客户通过登录网站后,可以对产品提交买卖价格,系统有个集中展示屏幕来展示10档最优买入和卖出价格。对于上述功能的实现无外乎有两种实现方式:
推送(Push)技术:
一种建立在服务器上的机制,由服务器主动将信息发往客户端的技术。Push技术的优势在于信息主动性和及时性。
拉(Pull)技术:
客户机主动请求信息,采用客户端定时刷新页面,可使用Ajax技术实现,每隔N秒自动Reload一次,如果在此期间Server端数据发生变化,客户端可以获取新的内容。
根据我们的需求,采用推送技术来实现上述功能是个比较好的选择。经过技术选型,最终选择使用Pushlet框架。Pushlet采用观察者模式,客户端订阅服务器感兴趣的事件,服务器端为每个客户端分配一个Session ID为标记,事件源会把新产生俄事件以多播的方式发送到订阅者的事件队列里。具体原理这里不作过多介绍,本文主要介绍一下使用Pushlet实现的一个计算报价平均值的Demo。
新建一个QuoteServlet.类,一个Servlet用于实现从客户端提交用户的报价,并触发服务器端发送价格变动事件。
package com; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /* * Servlet方法实现数据的提交 */ public class QuoteServlet extends HttpServlet{ private static final long serialVersionUID = 2386052823761867369L; public static Double ttPrice = 0.00; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ // 调用 HttpServlet 自带的日志函数输出信息到控制台 this.log("执行 doGet 方法... "); // 处理 doPost this.execute(request, response); //调用pushlet更新对方的数据 String valueString = Double.toString(ttPrice); QuotePushlet.sendByMulticast(valueString); } /** * 以 POST 方式访问页面时执行该函数。 */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.log("执行 doPost 方法... "); // 处理 doPost this.execute(request, response); //调用pushlet更新对方的数据 String valueString = Double.toString(ttPrice); //定向广播 //QuotePushlet.sendByMulticast(valueString); //定向发送 QuotePushlet.sendByUnicast(valueString); //QuotePushlet.sendByBroadcast(valueString); } private void execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ String priceString = getReqStr(request.getParameter("qprice"),true); Double priceDb = 0.0; if (priceString != null && priceString != ""){ priceDb = Double.valueOf(priceString); } if (ttPrice != 0.00){ ttPrice = ttPrice + priceDb; ttPrice = ttPrice/2; }else{ ttPrice = priceDb; } } private String getReqStr(Object s,boolean isGetMethod){ if(s==null) return ""; if(!isGetMethod) return ((String)s).toString(); try{ return new String(((String)s).toString().getBytes("ISO8859_1"), "GBK"); }catch(Exception e){ return ""; } } }
package com; import java.util.HashMap; import java.util.Map; import nl.justobjects.pushlet.core.Dispatcher; import nl.justobjects.pushlet.core.Event; import nl.justobjects.pushlet.core.Session; import nl.justobjects.pushlet.core.SessionManager; /* * 使用push的broadcast,multicast,unicast方法 * * 实现数据的展示 */ public class QuotePushlet { public static void sendByMulticast(String value){ Map<String, String> map = new HashMap<String, String>(); map.put("avgPrice", value); Event event = null; event = Event.createDataEvent("/quote/newPrice", map); //群发广播 Dispatcher.getInstance().multicast(event); } public static void sendByUnicast(String value){ Map<String, String> map = new HashMap<String, String>(); map.put("avgPrice", value); Event event = null; event = Event.createDataEvent("/quote/newPrice", map); Session[] sessions = SessionManager.getInstance().getSessions(); for ( Session session : sessions ) { //定向发送 Dispatcher.getInstance().unicast(event, session.getId()); } } public static void sendByBroadcast(String value){ Map<String, String> map = new HashMap<String, String>(); map.put("avgPrice", value); Event event = null; event = Event.createDataEvent("/quote/newPrice", map); Dispatcher.getInstance().broadcast(event); } }使用pushlet需要在Web.xml里进行配置。
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- Define the pushlet servlet --> <servlet> <servlet-name>pushlet</servlet-name> <servlet-class>nl.justobjects.pushlet.servlet.Pushlet</servlet-class> <load-on-startup>3</load-on-startup> </servlet> <!-- Define the Servlet Mappings. --> <!-- The pushlet --> <servlet-mapping> <servlet-name>pushlet</servlet-name> <url-pattern>/pushlet.srv</url-pattern> </servlet-mapping> <servlet> <servlet-name>quoteServlet</servlet-name> <servlet-class> com.QuoteServlet </servlet-class> </servlet> <servlet-mapping> <servlet-name>quoteServlet</servlet-name> <url-pattern>/quoteServlet</url-pattern> </servlet-mapping> </web-app>
报价的JSP页面代码如下:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>quote</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="Pragma" content="no-cache"> <script type="text/javascript" src="ajax-pushlet-client.js"></script> <link rel="stylesheet" type="text/css" href="./script/easyui/jquery-easyui-1.3.5/easyui.css" > <link rel="stylesheet" type="text/css" href="./script/easyui/jquery-easyui-1.3.5/icon.css" > <script type="text/javascript" src="./script/easyui/jquery.min.js"></script> <script type="text/javascript" src="./script/easyui/jquery.easyui.min.js"></script> <style type="text/css" ID="PageStyle"> body, td { background: #ffffff; color: #000000; font-size: 14px; font-family : verdana, sans-serif; } body { margin-left: 8px; margin-right: 0px; } .head { color: #111111; } </style> <script type="text/javascript"> function QuotationPost(){ $.ajax({ type: "post", url: "quoteServlet", dataType: "text", data:{qprice:$("#formqprice").val()}, success: function (data) { }, error: function (XMLHttpRequest, textStatus, errorThrown) { alert(errorThrown); } }); } </script> </head> <body> <div> <span>当前债券的平均价格是</span> <span id="qprice"></span> <br> </div> <div> <span>我要报价:</span> <div style="font-size: 20px;" > <form id="QuotationForm" method="post" > <table> <tr> <td colspan="3" > 报价: <input name="qprice" id="formqprice" type="text" style="width:100px" /> </td> </tr> <tr> <td colspan="2" > <input type="button" value="提交报价" onclick="QuotationPost();" /> </td> </tr> </table> </form> </div> </div> </body> </html>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Pragma" content="no-cache" /> <script type="text/javascript" src="ajax-pushlet-client.js"></script> <script type="text/javascript"> PL._init(); PL.joinListen('/cuige/he'); function onData(event) { //alert(event.get("mmdata")); // 离开 // PL.leave(); var kbDom = document.getElementById('kb'); var kb = event.get("mess"); //alert(event.get("mmdata")); kbDom.innerHTML = kb; } </script> </head> <body> 当前债券平均价格:<span id="kb">...</span>元 </body> </html>