一、股票案例

我们要做的是股票的案例,它能够无刷新地更新股票的数据。当鼠标移动到具体的股票中,它会显示具体的信息。

我们首先来看一下要做出来的效果:

1.1服务器端分析

首先,从效果图我们可以看见很多股票基本信息:昨天收盘价、今天开盘价、最高价、最低价、当前价格、涨幅。这些信息我们用一个类来描述出来。

我们发现数据是定时刷新的,于是我们需要一个定时器。

服务器端的数据和客户端交互,我们使用JSON吧

1.2服务器端代码

1.2.1Stock股票类的代码

  • 股票基本信息:
private String id;private String name;private double yesterday;private double today ;private double highest;private double lowest;private double current;private String range ;//各种setter和getter
  • Stock的构造函数:
/*** id,name,yesterday这三个参数都是固定的,其他的属性都是可变的。* 因此我们构造函数就传入这三个值* */
public Stock(String id, String name, double yesterday) {this.id = id;this.name = name;this.yesterday = yesterday;//把开盘价设定为-1,后面在定时器计算出来的随机数,如果发现开盘价是-1,就设置第一次的随机数为开盘价this.today = -1;//把最高、最低、当前的价格都暂且设置成昨天的开盘价,后面我们可以变化的this.highest = yesterday;this.current = yesterday;this.lowest = yesterday;}
  • setCurrent()方法代码:
/*** 每次设置当前价钱的时候,最高、最低、涨幅都应该随着当前价钱而变化的*/
public void setCurrent(double current) {//计算出涨幅或跌幅double range = (current - this.yesterday) / this.yesterday;//设置涨幅和跌幅不能超过10%,当前的价格只能是昨天开盘价的1.1倍或0.9倍//当前价格应该是两位小数DecimalFormat formatPrice = new DecimalFormat("#.00");if (range > 0.1) {current = Double.parseDouble(formatPrice.format(this.yesterday * 1.1));}if (range < -0.1) {current = Double.parseDouble(formatPrice.format(this.yesterday * 0.9));}this.current = current;//如果今天开盘价没设定,那么就将第一次的当前价作为今天的开盘价if (this.today == -1) {this.today = this.current;}//比较最大值和最小值if (this.current > this.highest) {this.highest = this.current;}if (this.current < this.lowest) {this.lowest = this.current;}//格式化涨幅的字符串,整数两位,小数两位DecimalFormat formatRange = new DecimalFormat("##.##%");this.range = formatRange.format(range);
}

1.2.2Servlet的代码

  • init()初始化代码:

/*** 重写init()方法,加入一些配置内容*/
@Override
public void init(ServletConfig config) throws ServletException {map = new HashMap<>();//新建几只固定的股票final Stock zhong = new Stock("1", "百度", 1110.1);final Stock fu = new Stock("2", "阿里", 222.2);final Stock cheng = new Stock("3", "腾讯", 333.3);final Stock ou = new Stock("4", "谷歌", 1133.5);//添加到容器中map.put("1", zhong);map.put("2", fu);map.put("3", cheng);map.put("4", ou);//生成随机数final Random random = new Random();//格式化生成的随机数final DecimalFormat format = new DecimalFormat("#.00");//Servlet被启动后1秒开始,每两秒扫描一次timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {double baidu = random.nextDouble() * 1.1;double ali = random.nextDouble() * 2;double tengxun = random.nextDouble() * 0.3;double geogle = random.nextDouble() * 4;//概率大致都是50%,我们用来做正负if (random.nextBoolean()) {baidu = 0 - baidu;}if (random.nextBoolean()) {ali = 0 - ali;}if (random.nextBoolean()) {tengxun = 0 - tengxun;}if (random.nextBoolean()) {geogle = 0 - geogle;}//设置它们的当前价格zhong.setCurrent(Double.parseDouble(format.format(zhong.getCurrent()+baidu)));fu.setCurrent(Double.parseDouble(format.format(fu.getCurrent()+ali)));cheng.setCurrent(Double.parseDouble(format.format(cheng.getCurrent()+tengxun)));ou.setCurrent(Double.parseDouble(format.format(ou.getCurrent()+geogle)));}}, 1000, 2000);}
  • 服务器一启动就应该初始化Servlet
<servlet><servlet-name>Refresh</servlet-name><servlet-class>Refresh</servlet-class><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>Refresh</servlet-name><url-pattern>/Refresh</url-pattern>
</servlet-mapping>
  • doPost()代码:
//封装成JSON格式,返回给浏览器
StringBuffer buffer = new StringBuffer();//这里我们拼接成4个对象
buffer.append("({");
for (Map.Entry<String, Stock> entry : map.entrySet()) {String id = entry.getKey();Stock stock = entry.getValue();buffer.append(id).append(":{yesterday:").append(stock.getYesterday()).append(",today:").append(stock.getToday()).append(",high:").append(stock.getHighest()).append(",low:").append(stock.getLowest()).append(",current:").append(stock.getCurrent()).append(",range:'").append(stock.getRange()).append("'}").append(",");}
//消除最后一个逗号
buffer.deleteCharAt(buffer.lastIndexOf(","));//最后补上括号
buffer.append("})");//返回给浏览器
response.getWriter().write(buffer.toString());
  • 拼接成的JSON数据:
({3:{yesterday:333.3,today:333.48,high:333.48,low:333.3,current:333.48,range:'0.05%'},2:{yesterday:222.2,today:223.46,high:223.46,low:222.2,current:223.46,range:'0.57%'},1:{yesterday:1110.1,today:1109.73,high:1110.1,low:1109.73,current:1109.73,range:'-0.03%'},4:{yesterday:1133.5,today:1135.49,high:1135.49,low:1133.5,current:1135.49,range:'0.18%'}
})

1.3客户端分析之一

客户端要做的就是显示数据,每隔两秒就和服务器进行一次交互

  • 用到Ajax和setInterval()方法

1.3.1html代码

使用div嵌套span和a标签来进行显示,span装载的就是服务端返回json的current数据

<body onload="show()"><div><a href="#">百度:</a><span id="1"></span>
</div>
<div><a href="#">阿里巴巴:</a><span id="2"></span>
</div>
<div><a href="#">腾讯:</a><span id="3"></span>
</div>
<div><a href="#">谷歌:</a><span id="4"></span>
</div></body>

1.3.2javaScript代码

  • 解析JSON,并设置span的内容
function show() {getStock();//每两秒就取一次数据setInterval(getStock, 2000);}
var httpRequest;
function getStock() {//力求是最新的响应数据,如果存在httpRequest,那么将上次的httpRequest终止if(httpRequest) {httpRequest.abort();}httpRequest= new XMLHttpRequest();httpRequest.open("GET", "Refresh", true);httpRequest.onreadystatechange = callBackFunction;httpRequest.send(null);}function callBackFunction() {if(httpRequest.readyState==4) {if(httpRequest.status==200) {//得到服务器端返回的JSON数据var text = httpRequest.responseText;//解析成JavaScript对象var json = eval(text);//遍历出每个JSON对象【也就是json的id】for(var id in json) {//得到每个stock对象var stock = json[id];//将当前的价格设置到span节点里面document.getElementById(id).innerHTML = stock.current;//比较当前价格和昨天开盘价格,如果大于就是红色,小于就是绿色if(stock.current>stock.yesterday) {document.getElementById(id).style.color = 'red';}else {document.getElementById(id).style.color = 'green';}}}}
}
  • 效果


1.4客户端分析之二

当鼠标移动到具体的股票超链接的时候,会显示具体的数据,并且数据是动态的

  • 在超链接上绑定事件
  • 取出和服务器交互的数据,显示在页面上

1.4.1html代码:

绑定事件,只要鼠标移动到超链接上就触发事件


<body onload="show()"><div><a href="#" onmouseover="showTool(this)" onmouseleave="clearTool()">百度:</a><span id="1"></span>
</div>
<div><a href="#" onmouseover="showTool(this)" onmouseleave="clearTool()">阿里巴巴:</a><span id="2"></span>
</div>
<div><a href="#" onmouseover="showTool(this)" onmouseleave="clearTool()">腾讯:</a><span id="3"></span>
</div>
<div><a href="#" onmouseover="showTool(this)" onmouseleave="clearTool()">谷歌:</a><span id="4"></span>
</div><div id="toolTip"><div>昨收:<span id="yesterday"></span></div><div>今收:<span id="today"></span></div><div>最低:<span id="low"></span></div><div>当前:<span id="current"></span></div><div>最高:<span id="high"></span></div><div>涨幅:<span id="range"></span></div>
</div></body>

1.4.2css代码

详细框的信息默认是隐藏的

<style type="text/css">#toolTip {border: 1px solid #000;width: 150px;position: absolute;display: none;}</style>

1.4.3javaScript代码

得到交互的数据,设置span里面的值


function update() {var stock = json[sid];//得到相对应的控件var yesterday = document.getElementById("yesterday");var today = document.getElementById("today");var low = document.getElementById("low");var high = document.getElementById("high");var range = document.getElementById("range");var current = document.getElementById("current");//设置具体信息的值high.innerHTML = stock.high;range.innerHTML = stock.range;current.innerHTML = stock.current;yesterday.innerHTML = stock.yesterday;today.innerHTML = stock.today;low.innerHTML = stock.low;//如果数值比昨天开盘价低,反则就是红色if (stock.today > stock.yesterday) {today.style.color = 'red';} else {today.style.color = 'green';}if (stock.low > stock.yesterday) {low.style.color = 'red';} else {low.style.color = 'green';}if (stock.high > stock.yesterday) {high.style.color = 'red';} else {high.style.color = 'green';}//如果现在的价格比昨天开盘高,那么涨幅是红色if (stock.current > stock.yesterday) {range.style.color = 'red';current.style.color = 'red';} else {range.style.color = 'green';current.style.color = 'green';}
}

只有鼠标移到超链接上,才明确id的值是多少!

function callBackFunction() {if (httpRequest.readyState == 4) {if (httpRequest.status == 200) {//得到服务器端返回的JSON数据json= eval(httpRequest.responseText);//更新详细框的数据,当鼠标移动到超链接上才确定有id,于是判断有没有idif(sid) {update();}//遍历出每个JSON对象【也就是json的id】for (var id in json) {//得到每个stock对象var stock = json[id];//将当前的价格设置到span节点里面document.getElementById(id).innerHTML = stock.current;//比较当前价格和昨天开盘价格,如果大于就是红色,小于就是绿色if (stock.current > stock.yesterday) {document.getElementById(id).style.color = 'red';} else {document.getElementById(id).style.color = 'green';}}}}
}function showTool(node) {//得到鼠标移动到具体股票的idsid = node.parentNode.getElementsByTagName("span")[0].id;//把详细框框显示出来document.getElementById("toolTip").style.display = 'block';}
function clearTool() {document.getElementById("toolTip").style.display = 'none';
}

1.5最终效果:

1.6总结要点

①:这是由AJAX来实现的,因为它无刷新的动态交互数据。

②:服务器端应该保存着股票的基本信息。于是乎,我们用一个类来装载着这些信息【信息之间的关系就不一一说明了,因为每个案例用的可能都不一样】

③:用到了DecimalFormat类来格式化小数变为自己想要的格式

④:使用HashMap来装载这些股票,使用Map集合主要是在客户端中,可以通过键来访问具体的股票,只要能访问到股票了,那么一切就好说了。

⑤:当然啦,装载股票的任务就交给init()方法,因为只需要装载一次。

⑥:我们会发现,股票的信息是不断会变化的,所以我们使用定时器和Random类来不断修改股票的信息

⑦:JavaScript和服务端交互使用AJAX,要么使用XML,要么就是JSON,这次我们采用的是JSON

⑧:JavaScript使用XMLHttpRequest对象得到Servlet返回给浏览器的JSON数据,解析JSON数据,变成是JavaScript对象

⑨:在页面上显示服务端带过来的数据,一般都是使用div来显示【块级】,用控件绑定id,在JavaScript中得到控件,填充数据。这样就是动态地修改页面的数据了。

⑩:浏览器想要不断地从服务端获取股票的数据,那么就需要不断地与服务端交互,解析JSON,填充数据.....这种我们可以通过setInterval()定时器来做

①①:想要修改字体的颜色,只要获取它的控件再style.color就可以修改了。

①②:鼠标移动到具体的股票链接的时候,会出现股票的详细信息时,这明显就是为超链接绑定了事件

①③:股票的详细信息用一个框框装载着,那么我们就在css中初始化这个框框,它平时是不显示出来的,只用在鼠标移到它那里的时候才显示,我们把display=“none”就行了。

①④:在响应事件的时候,我们需要知道用户是移动到哪一个超链接上,所以要获取得到具体的超链接id。知道id以后,我们就知道用户想要知道的股票是哪一个了。

①⑤:股票的信息也想要及时的更新,那么我们想把它抽取成一个方法,在AJAX回调方法中加入进去就行了。当然了,id和具体股票对象应该是全局的变量【这样才能够在别的方法中用到】

二、验证码校验

对于验证码检查我们并不会陌生,我们在学习Session的时候已经使用过了验证码检查了。详细可参考:http://blog.csdn.net/hon_3y/article/details/54799494#t11

我们当时是同步检查验证码是否正确的,其实没有必要。因为就验证一个输入框的数据,没必要使用同步的方式验证【使用异步对用户体验更加友好】

2.1分析

当用户输入完4位数字的时候,就去服务器端验证是否需要相同,如果相同,那么返回一个打钩的图片。如果不同,那么就返回一个打叉的图片

2.1.1前台分析

  • 绑定键盘输入事件
  • 当输入数达到4的时候,就与服务器交互
  • 得到服务器带过来的图片,使用DOM添加到对应的位置

2.1.2后台分析

  • 得到前台带过来的值
  • 判断该值与Session保存的是否相同
  • 根据判断值返回对应的图片

2.2编写JSP

值得注意的是:要获取td定义的id,外边一定要套上table标签。。。我在刚开始写的时候,是没有table标签的。然后死活得不到td的标签....很烦...


<%--Created by IntelliJ IDEA.User: ozcDate: 2017/5/17Time: 20:52To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>验证码校验</title><script type="text/javascript" src="js/ajax.js"></script>
</head>
<body><%--###################展示页面#############################--%><table><tr><td>验证码:</td><td><input type="text" id="checkCode" name="checkCode"></td><td><img src="01_image.jsp"/></td><td id="result"></td></tr>
</table><%--###################去除空格方法#############################--%>
<script type="text/javascript">function trim(str) {//去除左边的空格str.replace("/^\s*/", "");//去除右边的空格str.replace("/\s*$/", "");return str;}
</script><%--###################绑定键盘事件#############################--%><script type="text/javascript">document.getElementById("checkCode").onkeyup = function () {//得到输入框的内容,把的前后空格都去除var keyValue = this.value;keyValue = trim(keyValue);/*******************ajax代码*******************************/if (keyValue.length == 4) {var ajax = createAJAX();var method = "post";var url = "${pageContext.request.contextPath}/CheckCodeServlet?time=" + new Date().getTime();ajax.open(method, url);ajax.setRequestHeader("content-type", "application/x-www-form-urlencoded");ajax.send("keyValue=" + keyValue);/*******************ajax回调函数*******************************/ajax.onreadystatechange = function () {if (ajax.readyState == 4) {if (ajax.status == 200) {//得到服务器带过来的数据var tip = ajax.responseText;/*******************使用DOM把数据添加到页面上*******************************/var img = document.createElement("img");img.src = tip;img.style.width = "14px";img.style.height = "14px";var td = document.getElementById("result");td.innerHTML = "";td.appendChild(img);}}};}else {//清空图片var td = document.getElementById("result");td.innerHTML = "";}};</script></body>
</html>
  • 处理请求的Servlet

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;/*** Created by ozc on 2017/5/17.*/
@WebServlet(name = "CheckCodeServlet",urlPatterns = "/CheckCodeServlet")
public class CheckCodeServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//得到带过来的数据String keyValue = request.getParameter("keyValue");//得到Session中的数据String checkCodeInSession = (String) request.getSession().getAttribute("CHECKNUM");response.setContentType("text/html;charset=UTF-8");String src = "images/MsgError.gif";//判断俩数据是否相同if (keyValue.equals(checkCodeInSession)) {src = "images/MsgSent.gif";}PrintWriter writer = response.getWriter();writer.write(src);writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}
}

2.3测试


2.4总结

  • 使用AJAX验证校验码主要是监听键盘的响应事件

    • 要获取td标签的数据,外边一定要套有table标签!【别偷懒不写table标签】
    • 当输入框的数值数为4的时候就与服务器进行交互,服务器返回一张图片。
    • 可以用自定义的trim()把数据的前后空格去掉,通过正则表达式来去除空格。
    • 当输入框的数值数不为4的时候就把图片的内容清空

如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章的同学,可以关注微信公众号:Java3y

AJAX应用【股票案例、验证码校验】相关推荐

  1. jQuery ajax简单案例-验证用户名是否可用

    jQuery ajax简单案例-验证用户名是否可用 HTML <!DOCTYPE html> <html> <head> <meta charset=&quo ...

  2. java ajax 登陆验证,Spring Security4实例(Java config版)——ajax登录,自定义验证

    本文源码请看这里 首先添加起步依赖(如果不是springboot项目,自行切换为Spring Security依赖) org.springframework.boot spring-boot-star ...

  3. 在我的新书里,尝试着用股票案例讲述Python爬虫大数据可视化等知识

    我的新书,<基于股票大数据分析的Python入门实战>,预计将于2019年底在清华出版社出版. 如果大家对大数据分析有兴趣,又想学习Python,这本书是一本不错的选择.从知识体系上来看, ...

  4. JavaWeb-----Ajax异步请求 json对象 服务器如何返回json数据 使用ajax完成一个案例

    1. 回顾 1. servlet的生命周期: 2. filter: 过滤放行和拦截一些资源.比如:黑白名单,登录校验,编码设置等.    (1)创建一个类并实现Filter接口以及重写接口的抽象方法 ...

  5. 注册验证码校验-立即校验

    注册验证码校验 1.     校验方式 输入后直接校验有好几种方式,之前一直再用的是onblur事件,当失去焦点是验证,但是注册码校验通常是最后一个表单输入,用户输入完直接点击提交,就会执行onblu ...

  6. SpringBoot+Vue项目中实现登录验证码校验

    SpringBoot+Vue项目中实现登录验证码校验 在各大项目中,为保证数据的安全性,通常在登录页面加入验证码校验,以防止爬虫带来的数据泄露危机.本文将介绍在前后端分离的项目中,怎样实现图形验证码校 ...

  7. insert时调用本身字段_MySQL RC级别下并发insert锁超时问题 - 案例验证

    作者:网易数据库团队 DDB(网易杭研自研的MySQL数据库中间件产品)团队小伙伴发现了一个问题,觉得比较奇怪.于是找到我们,希望解释下.过程中除解释了问题的现象,也通过代码了解了更多的InnoDB ...

  8. Java用户注册手机短信验证码校验功能实现

    验证用户提交的手机短信验证码,如果验证码错误就跳回到当前页面.在短信验证码未填写或未正确填写时,就关闭底下注册按钮的功能,只有短信验证码通过校验后才打开注册按钮的功能.第二种方式是所有输入项全部填写完 ...

  9. JavaWeb简单的单点登录、验证码校验功能实现

    前言 最近项目刚刚告一段落,后期有时间会慢慢分解整理出来给大家分享.本文主要提供思路和核心代码,建立在有一定后台基础读者上.(相信没有基础的同学只要认真细读也是可以理解的) 技术原理 1.单点登录(S ...

最新文章

  1. windows程序消息机制(Winform界面更新有关)--转
  2. Python基础教程:format 格式化字符串用法
  3. 详解yarn的resource manager组件
  4. wxWidgets:wxPen类用法
  5. jzoj3410-[GDOI2014模拟]Tree【最小生成树,贪心】
  6. JUC:ConcurrentHashMap(并发容器)
  7. javascript生成n至m的随机整数
  8. dubbo service注解用法_dubbo学习(四)配置dubbo 注解方式配置
  9. LayaAir 事件 laya.events.Event
  10. 完全卸载MySQL的方法
  11. 用友U8案例教程委外管理前台操作
  12. Java基础知识面试题(2022版)
  13. 十二、React脚手架
  14. 计算机关闭地址栏历史,删除win10地址栏历史记录方法
  15. .NET MAUI 性能提升
  16. 计算机认知训练效果,为轻度认知功能障碍的人保持认知功能而进行的计算机化认知训练...
  17. 线索树找*p的中序后继且中序遍历 二叉线索树
  18. 经颅电刺激促进睡眠振荡及其功能耦合增强轻度认知障碍患者的记忆巩固
  19. 数字化转型具体包含哪些内容?
  20. win10系统,点击连接校园网WLAN后,弹不出登录网页

热门文章

  1. 基于float的几种布局
  2. 编程题:编写一个函数string_copy()完成strcpy()的作用,并验证。
  3. nginx与apache详细性能对比
  4. 一个民工的数字化生活
  5. JAVA中利用DOM解析XML文档
  6. NumPy - np.linspace()
  7. 两种方式解决 生产者消费者问题
  8. Codeforces Gym 100269G Garage 数学
  9. 有关 iOS 的开发证书、应用标识、设备标识、配置文件以及密钥 #DF...
  10. 后台和前台对转义符号'/'同时起作用的例子