咱们要作的是股票的案例,它可以无刷新地更新股票的数据。当鼠标移动到具体的股票中,它会显示具体的信息。javascript
咱们首先来看一下要作出来的效果:css
首先,从效果图咱们能够看见不少股票基本信息:昨天收盘价、今天开盘价、最高价、最低价、当前价格、涨幅。这些信息咱们用一个类来描述出来。html
咱们发现数据是定时刷新的,因而咱们须要一个定时器。java
服务器端的数据和客户端交互,咱们使用JSON吧node
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
复制代码
/** * 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;
}
复制代码
/** * 每次设置当前价钱的时候,最高、最低、涨幅都应该随着当前价钱而变化的 */
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);
}
复制代码
/** * 重写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-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>
复制代码
//封装成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());
复制代码
({
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
使用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>
复制代码
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';
}
}
}
}
}
复制代码
当鼠标移动到具体的股票超连接的时候,会显示具体的数据,而且数据是动态的json
绑定事件,只要鼠标移动到超连接上就触发事件浏览器
<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>
复制代码
详细框的信息默认是隐藏的服务器
<style type="text/css">
#toolTip {
border: 1px solid #000;
width: 150px;
position: absolute;
display: none;
}
</style>
复制代码
获得交互的数据,设置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来实现的,由于它无刷新的动态交互数据。
②:服务器端应该保存着股票的基本信息。因而乎,咱们用一个类来装载着这些信息【信息之间的关系就不一一说明了,由于每一个案例用的可能都不同】
③:用到了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的时候已经使用过了验证码检查了。详细可参考:blog.csdn.net/hon_3y/arti…
咱们当时是同步检查验证码是否正确的,其实没有必要。由于就验证一个输入框的数据,不必使用同步的方式验证【使用异步对用户体验更加友好】
当用户输入完4位数字的时候,就去服务器端验证是否须要相同,若是相同,那么返回一个打钩的图片。若是不一样,那么就返回一个打叉的图片
值得注意的是:要获取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>
复制代码
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);
}
}
复制代码
若是文章有错的地方欢迎指正,你们互相交流。习惯在微信看技术文章的同窗,能够关注微信公众号:Java3y