实例内容
实例的具体内容是:服务端每隔指定时间产生股价,并计算涨幅,然后以json数据格式发送给客户端页面;客户端页面每隔指定时间重新获取服务端数据,解析json数据格式,并显示涨停。
实例来源于王兴魁Ajax教学视频,视频中用的是NetBeans环境Java语言编写的,使用NetBeans按教程编写不是很难,所以想着用VS2010环境C#编写,代码如下。
实例代码
Stocks.cs
Stock.cs,股票类代码:
/// <summary>
///股票信息类
/// </summary>
public class Stock
{
public Stock(string id,string name,double yesterday)
{
this.sid = id;
this.name = name;
this.yesterday = yesterday;
this.today = -1;
this.highest = yesterday;
this.current = yesterday;
this.lowest = yesterday;
}
//股票ID
private string sid;
//股票名
private string name;
//昨日股价
private double yesterday;
//今日股价
private double today;
//最高
private double highest;
//最低
private double lowest;
//当前股价
private double current;
//浮动
private string range;
/// <summary>
/// 获取当前股价
/// </summary>
/// <returns></returns>
public double GetCurrent()
{
return current;
}
/// <summary>
/// 获取昨日股价
/// </summary>
/// <returns></returns>
public double GetYesterday()
{
return yesterday;
}
/// <summary>
/// 获取今日股价
/// </summary>
/// <returns></returns>
public double GetToday()
{
return today;
}
/// <summary>
/// 获取最高股价
/// </summary>
/// <returns></returns>
public double GetHighest()
{
return highest;
}
/// <summary>
/// 获取最低股价
/// </summary>
/// <returns></returns>
public double GetLowest()
{
return lowest;
}
/// <summary>
/// 获取浮动值
/// </summary>
/// <returns></returns>
public string GetRange()
{
return range;
}
public void SetRange(string range)
{
this.range = range;
}
/// <summary>
/// 设置当前股票价格
/// </summary>
/// <param name="current">当前股指</param>
public void SetCurrent(double current)
{
//计算涨幅
double range = (current - this.yesterday ) / this.yesterday ;
//如果涨幅超过10%
if (range > 0.1)
{
current = Math.Round(1.1 * this.yesterday * 100) / 100.0;
}
//如果跌幅超过10%
if (range < -0.1)
{
current = Math.Round(0.9 * this.yesterday * 100) / 100.0;
}
this.current = current;
//尚未开盘时,利用第一次的current设置开盘股价
if (this.today == -1)
{
this.today = current;
}
//根据涨跌形势设置今日股价
if (this.current > this.highest)
{
this.highest = this.current;
}
else if (this.current < this.lowest)
{
this.lowest = this.current;
}
//
this.range = range.ToString("p");
}
}
xmlhttp.js
xmlhttp.js,自定义的MyXMLHttpRequest"类",主要负责和服务端的交互:
// 使用封装方法的人只关心http的请求方法,url地址,数据,成功和失败的回调方法
// 类的构造方法,主要职责是新建XMLHttpRequest对象
var MyXMLHttpRequest = function(){
var xmlhttprequest;
if(window.XMLHttpRequest){
xmlhttprequest = new XMLHttpRequest();
if(xmlhttprequest.overrideMineType){
xmlhttprequest.overrideMineType("text/xml");
}
}else if (window.ActiveXObject) {
var activeName = ["XSXML2.XMLHTTP","Microsoft.XMLHTTP"];
for (i = 0; i < activeName.length; i++) {
try {
xmlhttprequest = new ActiveXObject(activeName[i]);
break;
} catch (e) {
}
}
}
if (xmlhttprequest == undefined || xmlhttprequest == null) {
alert("xmlhttprequest对象创建失败!");
}else{
this.xmlhttp = xmlhttprequest;
}
}
// 用户发送请求的方法
MyXMLHttpRequest.prototype.send = function(method,url,data,callback,failback){
if (this.xmlhttp != undefined || this.xmlhttp != null) {
method = method.toUpperCase();
if (method != "GET" && method != "POST") {
alert("HTTP请求方法必须是GET或POST");
return ;
}
if (url == undefined || url == null) {
alert("http请求地址必须设置");
return;
}
var tempxmlhttp = this.xmlhttp;
tempxmlhttp.onreadystatechange = function(){
if (tempxmlhttp.readyState == 4) {
if (tempxmlhttp.status == 200) {
var responseText = tempxmlhttp.responseText;
var responseXML = tempxmlhttp.responseXML;
if (callback == undefined || callback == null) {
alert("没有设置处理数据正确返回的方法");
alert("返回的数据:" + responseText);
}
else{
callback(responseText,responseXML);
}
}else {
if (failback == undefined || failback == null) {
alert("没有设置处理数据返回失败的处理方法");
alert("Http响应码信息:" + tempxmlhttp.status + ",响应码文本信息:" + tempxmlhttp.statusText)
return ;
}else{
failback(tempxmlhttp.status,tempxmlhttp.statusText);
}
}
}
}
// 解决缓存的转换
if (url.indexOf("?") >= 0) {
url = url + "&t=" + (new Date()).valueOf();
}else{
url = url + "?t=" + (new Date()).valueOf();
}
// 解决跨域问题
if (url.indexOf("http://") >= 0) {
url.replace("?","&");
url = url + "Proxy?url=";
}
this.xmlhttp.open(method,url,true);
// 如果是POST方式,需要设置请求头
if (method == "POST") {
this.xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
}
this.xmlhttp.send(data);
}else{
alert("XMLHttpRequest对象创建失败,无法发送数据.");
}
}
MyXMLHttpRequest.prototype.abort = function(){
this.xmlhttp.abort();
}
Handler.aspx
一般处理文件Handler.ashx,用于处理客户端的请求:
<%@ WebHandler Language="C#" Class="Handler" %>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Threading;
//StringBuilder所在命名空间
using System.Text;
public class Handler : IHttpHandler {
//定义股票字典
private Dictionary<string, Stock> stock;
private System.Timers.Timer timer;
/// <summary>
/// 响应客户端请求
/// </summary>
/// <param name="context">请求信息</param>
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "text/html;charset=UTF-8";
//Response.ContentType = "text/html;charset=UTF-8";
初始化数据
Init();
//转换为json字符串
Thread.Sleep(200);
StringBuilder builder = new StringBuilder();
builder.Append("({");
//stockid数组
string[] StockId = new string[stock.Count];
//获取股票ID
for (int i = 0; i < stock.Count; i++)
{
StockId[i] = stock.ElementAt(i).Key.ToString();
}
//根据股票ID 得到股票,拼接字符串
for (int i = 0; i < stock.Count; i++)
{
string sid = StockId[i];
Stock tempStock = stock[sid];
builder.Append(sid).Append(":{yes:").Append(tempStock.GetYesterday()).Append(",tod:").Append(tempStock.GetToday()).Append(",high:").Append(tempStock.GetHighest()).Append(",low:").Append(tempStock.GetLowest()).Append(",cur:").Append(tempStock.GetCurrent()).Append(",ran:'").Append(tempStock.GetRange()).Append("'}");
//每个项后面再添加“,”
if (i < stock.Count)
{
builder.Append(",");
}
}
//尾部添加})
builder.Append("})");
//回复响应
context.Response.Write(builder);
}
/// <summary>
/// 初始化配置数据
/// </summary>
private void Init()
{
//新建四支股票
Stock szzs = new Stock("300001", "上证指数", 300);
Stock pfyh = new Stock("600000", "浦发银行", 25);
Stock gsyh = new Stock("601398", "工商银行", 6.5);
Stock zgsy = new Stock("601857", "中国石油", 19.1);
//设定股票字典
stock = new Dictionary<string, Stock>();
//添加股票
stock.Add("300001", szzs);
stock.Add("600000", pfyh);
stock.Add("601398", gsyh);
stock.Add("601857", zgsy);
//设置计时器参数,不要太大
timer = new System.Timers.Timer(50);
timer.Enabled = true;
//执行计时器函数theout
Random rdm = new Random();
//每次只去一个,防止循环执行获取随机数
double mdr = rdm.NextDouble();
//timer的振荡事件,采用匿名函数方式执行
timer.Elapsed += delegate(object source, System.Timers.ElapsedEventArgs e)
{
//股票变动范围
//上涨浮动
double sz = mdr * 30;
double pf = mdr * 0.5;
double gs = mdr * 0.1;
double zg = mdr * 0.3;
//下跌浮动
if (mdr > 0.5)
{
sz = 0 - sz;
}
if (mdr > 0.5)
{
pf = 0 - pf;
}
if (mdr > 0.5)
{
gs = 0 - gs;
}
if (mdr > 0.5)
{
zg = 0 - zg;
}
//当前股票价格
szzs.SetCurrent(Math.Round((szzs.GetCurrent() + sz) * 100) / 100.0);
pfyh.SetCurrent(Math.Round((pfyh.GetCurrent() + pf) * 100) / 100.0);
gsyh.SetCurrent(Math.Round((gsyh.GetCurrent() + gs) * 100) / 100.0);
zgsy.SetCurrent(Math.Round((zgsy.GetCurrent() + zg) * 100) / 100.0);
};
}
/// <summary>
/// 实现接口自带的函数
/// </summary>
public bool IsReusable {
get {
return false;
}
}
}
refresh.html
refresh.html,用于发送更新股票信息的请求:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css">
#tooltip{
display:none;
position:absolute;
border:1px solid black;
background-color: white;
z-index: 99;
width:135px;
}
</style>
<script src="Scripts/xmlhttp.js" type="text/javascript"></script>
<script type="text/javascript">
var xmlhttp;
var stocks;
var yesNode;
var todNode;
var highNode;
var lowNode;
var curNode;
var ranNode;
var tooltipNode;
var tooltipSid;
//获取tooltip下所有节点并交互
function show() {
// 获取tooltip相关的各个节点
yesNode = document.getElementById('yes');
todNode = document.getElementById('tod');
highNode = document.getElementById('high');
lowNode = document.getElementById('low');
curNode = document.getElementById('cur');
ranNode = document.getElementById('ran');
tooltipNode = document.getElementById('tooltip');
// 与服务端进行交互,获取到股票的最新消息
getStock();
// 以后每隔两秒再和服务端交互一次
setInterval(getStock, 5000);
}
// 与服务端进行交互,获取到股票的最新消息
function getStock() {
// 假如xmlhttp存在,则将上一次交互终止掉(防止两个交互返回的数据相互覆盖)
if (xmlhttp) {
xmlhttp.abort();
}
// 利用XMLHttpRequest对象和服务器进行交互
xmlhttp = new MyXMLHttpRequest();
xmlhttp.send('GET', 'Handler.ashx', '', callback, failback);
}
function callback(responseText, responseXML) {
try {
// 将服务端返回的JSON数据转换成js中的对象
stocks = eval(responseText);
// 更新ToolTip内容
updateToolTip();
// 遍历所有的股票
for (var sid in stocks) {
var spanNode = document.getElementById(sid);
// 获取某一只股票的昨天收盘价和当前价
var stock = stocks[sid];
var cur = stock.cur;
var yes = stock.yes;
// 将当前价设置到span的节点里面
spanNode.innerHTML = cur;
// 根据当前价格设置span中的文本是红色还是绿色
if (cur >= yes) {
spanNode.style.color = 'red';
} else {
spanNode.style.color = 'green';
}
}
} catch (exception) {
alert('解析服务器数据失败,错误内容为:' + exception.toString());
}
}
function failback(status, statusText) {
alert('回调函数失败:'+ statusText);
}
// 显示弹出框方法
function showToolTip(aNode, event) {
// 得到对应的股票代码
tooltipSid = aNode.parentNode.getElementsByTagName('span')[0].id;
// 更新ToolTip内容
updateToolTip();
var myevent = window.event || event;
var mouseX = myevent.clientX;
var mouseY = myevent.clientY;
tooltipNode.style.left = mouseX + 5 + 'px';
tooltipNode.style.top = mouseY + 5 + 'px';
tooltipNode.style.display = 'block';
}
隐藏弹出框方法
function clearToolTip() {
tooltipNode.style.display = 'none';
tooltipSid = undefined;
}
// 更新tooltip中的内容
function updateToolTip() {
if (tooltipSid)
{
// 当前股票的具体信息对象
var stock = stocks[tooltipSid];
// 设置昨收
var yes = stock.yes;
yesNode.innerHTML = yes;
// 设置今开
var tod = stock.tod;
todNode.innerHTML = tod;
if (tod >= yes) {
todNode.style.color = 'red';
} else {
todNode.style.color = 'green';
}
// 设置最高
var high = stock.high;
highNode.innerHTML = high;
// 设置最低
var low = stock.low;
lowNode.innerHTML = low;
if (low >= yes) {
todNode.style.color = 'red';
} else {
todNode.style.color = 'green';
}
// 设置当前价格和涨幅
var cur = stock.cur;
curNode.innerHTML = cur;
var ran = stock.ran;
ranNode.innerHTML = ran;
if (cur >= yes) {
curNode.style.color = 'red';
ranNode.style.color = 'red';
}
else
{
curNode.style.color = 'green';
ranNode.style.color = 'green';
}
}
}
</script>
</head>
<body οnlοad="show()">
<!--每支股票各占一个div-->
<div>
<a href="#" οnmοuseοver="showToolTip(this,event)" οnmοuseοut="clearToolTip()" >上证指数:</a>
<span id="300001"></span>
</div>
<div>
<a href="#" οnmοuseοver="showToolTip(this,event)" οnmοuseοut="clearToolTip()" >浦发银行:</a>
<span id="600000"></span>
</div>
<div>
<a href="#" οnmοuseοver="showToolTip(this,event)" οnmοuseοut="clearToolTip()" >工商银行:</a>
<span id="601398"></span>
</div>
<div>
<a href="#" οnmοuseοver="showToolTip(this,event)" οnmοuseοut="clearToolTip()" >中国石油:</a>
<span id="601857"></span>
</div>
<!--tooltip框-->
<div id="tooltip">
<div>昨收:<span id="yes"></span></div>
<div>今开:<span id="tod"></span></div>
<div>最高:<span id="high"></span></div>
<div>最低:<span id="low"></span></div>
<div>当前:<span id="cur"></span></div>
<div>涨幅:<span id="ran"></span></div>
</div>
</body>
</html>
运行结果
下载及预告
因为是从NetBeans环境下的Java语言转换为VS2010下的C#语言,中间碰到不少问题,这些问题会在下篇博客介绍,另附本实例的代码下载地址:http://download.csdn.net/detail/lidaasky/4927691。