项目的原因需要实现基于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 "";
}
}
}
创建QuotePushlet类,用于实现事件广播。我这边分别使用了Pushlet的unicast,multicast,broadcast来发送广播事件。其中unicast是定向发,multicast,broadcast都是全局广播。
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>
另外还需要pushlet.properties和sources.properties,这里不表啦。
报价的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="提交报价" οnclick="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>