執行個體內容
執行個體的具體內容是:服務端每隔指定時間產生股價,並計算漲幅,然後以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 onload="show()"><!--每支股票各佔一個div--> <div> <a href="#" onmouseover="showToolTip(this,event)" onmouseout="clearToolTip()" >上證指數:</a> <span id="300001"></span> </div> <div> <a href="#" onmouseover="showToolTip(this,event)" onmouseout="clearToolTip()" >浦發銀行:</a> <span id="600000"></span></div> <div> <a href="#" onmouseover="showToolTip(this,event)" onmouseout="clearToolTip()" >工商銀行:</a> <span id="601398"></span></div> <div> <a href="#" onmouseover="showToolTip(this,event)" onmouseout="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。