AJAX应用【股票案例、验证码校验】

小编 2026-06-28 阅读:1306 评论:0
股票案例我们要做的是股票的案例,它能够无刷新地更新股票的数据。当鼠标移动到具体的股票中,它会显示...

股票案例

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

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

AJAX应用【股票案例、验证码校验】

服务器端分析

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

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

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

服务器端代码

Stock股票类的代码

  • 股票基本信息:
    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);        }

Servlet的代码

  • 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() {            @Override            public 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%'}})

客户端分析之一

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

  • 用到Ajax和setInterval()方法

html代码

使用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>

javaScript代码

  • 解析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';                        }                    }                }            }        }
  • 效果

AJAX应用【股票案例、验证码校验】


客户端分析之二

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

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

html代码:

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

<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>

css代码

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

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

javaScript代码

得到交互的数据,设置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,于是判断有没有id                    if(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) {            //得到鼠标移动到具体股票的id            sid = node.parentNode.getElementsByTagName("span")[0].id;            //把详细框框显示出来            document.getElementById("toolTip").style.display = 'block';        }        function clearTool() {            document.getElementById("toolTip").style.display = 'none';        }

最终效果:

AJAX应用【股票案例、验证码校验】

总结要点

①:这是由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

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

AJAX应用【股票案例、验证码校验】

分析

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

前台分析

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

后台分析

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

编写JSP

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

<%--  Created by IntelliJ IDEA.  User: ozc  Date: 2017/5/17  Time: 20:52  To 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);    }}

测试

AJAX应用【股票案例、验证码校验】


总结

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

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

更多的文章可往:文章的目录导航
版权声明

本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。

热门文章
  • 机房智能化温湿度解决方式之POE供电以太网温湿度传感器

    机房智能化温湿度解决方式之POE供电以太网温湿度传感器
    机房智能化温湿度解决方式之POE供电以太网温湿度传感器 北京盈创力和电子科技有限公司 智能型TCP网口温湿度记录仪 北京IP网络温湿度记录仪厂家,北京盈创力和 北京智能型TCP网口温湿度记录仪IP网络温湿度记录仪是一种新型的基于TCP/IP协议双绞线以太网标准温湿度采集模块,利用它可以实现现场温度值、相对湿度值的采集,同时利用其自身的RJ45通信接口可以方便地和机房监控主机或交换机集线器进行联网。 工作于-40℃~85℃工业级带...
  • Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering

    Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering
    Problem Statement 我们考虑一个具有马尔可夫性质、非线性、非高斯的状态空间模型(State Space Model):对于一个时间序列上的观测结果{yt,t∈N}\\{ y_t , t \\in N \\}{yt​,t∈N},我们认为每个观测结果yty_tyt​的生成依赖于一个无法直接观察的隐变量xt∈{xt,t∈N}x_t \\in \\{x_t , t \\in N \\}xt​∈{xt​,t∈N},即:p(...
  • HTTP状态保持的原理

    HTTP状态保持的原理
    a)在用户登录之后,浏览器返回响应的时候会在响应中添加上cookieb)浏览器接收到cookie之后会自动保存c)当用户再次请求同一服务器中的其他网页的时候,浏览器会自动带上之前保存的cookied)服务接收到请求之后可以请 request 对象中取到cookie 判断当前用户是否登录  Http是无状态的,就是连接时数据互通,关闭后...
  • CSRF的原理和防范措施

    CSRF的原理和防范措施
    a)攻击原理:i.用户C访问正常网站A时进行登录,浏览器保存A的cookieii.用户C再访问攻击网站B,网站B上有某个隐藏的链接或者图片标签会自动请求网站A的URL地址,例如表单提交,传指定的参数iii.而攻击网站B在访问网站A的时候,浏览器会自动带上网站A的cookieiv.所以网站A在接收到请求之后可判断当前用户是登录状态,所以...
  • Hive 系统函数及示例

    Hive 系统函数及示例
    查看所有系统函数 show functions; 函数分类 内置函数【系统函数】 数学函数: floor、round、ceil、cos、log2等 字符串函数: length、reverse、trim、lower、get_json_object、repeat等 收集函数: size 转换函数: cast 日期函数: year、month、datediff、date、date_add等 条件函数: coalesce、case…w...
标签列表