up:: 三个内置对象的属性的监听器
本篇博客是一个监听器案例;
其中涉及到了监听器的使用;
百度Echarts插件的使用;
JavaScript刷新函数的使用;
还有 一些编码思想和策略,都是可以参考 使用的!
零:需求描述
问题阐述:下面这个需求,很适合利用监听器来实现;
所以本案例主要包含两个部分:利用监听器实现对网站访问的量的获取;图表信息的展示;
一:具体实现:后台数据准备
1.第一部分:编写监听器
RequestTotalListener:监听器
(1)下面这个监听器编写方式,最重要的启发是: 一个问题,梳理清业务后,做好逻辑规划,然后按条理分别编写程序就行了 ;
(2)这个监听器内容其实很简单,大略看看就ok;
(3)全局对象ServletContext创建的时候,就在全局对象中初始化两个参数timeList和valueList;每当请求对象ServletRequest被创建的时候,就在timeList和valueList中做对应操作;
package com.imooc.total;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
/**
* (1)这个监听器需要实现ServletContextListener和ServletRequestListener接口;a
* @author Administrator
*
*/
public class RequestTotalListener implements ServletContextListener,ServletRequestListener{
@Override
public void contextDestroyed(ServletContextEvent sce) {
// TODO Auto-generated method stub
}
@Override
public void contextInitialized(ServletContextEvent sce) {
// TODO Auto-generated method stub
// 应用启动的时候,初始化需要存储的数据;
List timeList = new ArrayList<>(); // 存储时间
List valueList = new ArrayList<>(); // 具体时间的访问量数据
// 获取ServletContext对象,并将存储时间和访问量的值存储到这个对象中去;
// 即每次启动应用,在ServletContext全局对象中初始化这两个可以存储时间和访问量的属性;
sce.getServletContext().setAttribute("timeList",timeList);
sce.getServletContext().setAttribute("valueList", valueList);
}
@Override
public void requestDestroyed(ServletRequestEvent sre) {
// TODO Auto-generated method stub
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
// TODO Auto-generated method stub
// TimeList: 10:01 10:02 10:05
// ValueList: 3 6 1 这两个List中的值通过索引精准对应;
List<String> timeList = (List) sre.getServletContext().getAttribute("timeList");
List<Integer> valueList = (List) sre.getServletContext().getAttribute("valueList");
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
String time = sdf.format(date);
// indexOf()方法,查找对应的数据在集合中是否存在
if(timeList.indexOf(time) == -1) {
timeList.add(time); // 如果当前时间不存在,就把当前时间添加到timeList中去;
valueList.add(1);
sre.getServletContext().setAttribute("timeList", timeList);
sre.getServletContext().setAttribute("valueList", valueList);
}else {
// 获取当前时间在timeList中的索引,在valueList相同索引处的值+1;
// timeList和valueList,通过索引值的顺序一一对象;
valueList.set(timeList.indexOf(time), valueList.get(timeList.indexOf(time))+1);
sre.getServletContext().setAttribute("timeList", timeList);
sre.getServletContext().setAttribute("valueList", valueList);
}
}
}
2.第二部分:为了,模拟访问这个应用,添加了几个HTML页面(以供访问):
3.第三部分:为了将时间和访问数据展示到浏览器上,编写Servlet:RequestTotalServlet:
这个Servlet的左右就是,获取全局对象ServletContext中的timeList和valueList;并将其添加到响应中去;
package com.imooc.total;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class RequestTotalServlet
*/
@WebServlet("/rt")
public class RequestTotalServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public RequestTotalServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
List<String> timeList = (List)request.getServletContext().getAttribute("timeList");
List<Integer> valueList = (List)request.getServletContext().getAttribute("valueList");
response.setContentType("text/html;charset=utf-8");
response.getWriter().println(timeList.toString());
response.getWriter().println("<br/>");
response.getWriter().println(valueList.toString());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
4.第四部分,效果展示
至此,后台数据部分已经准备完成,启动应用,在浏览器对几个html访问几次(其实访问RequestTotalServlet也是可以的,都会有ServletRequest对象的创建啦):
二.疑问,如何让数据在前台展示的更美观?百度JS插件:Echarts插件
所以,后台数据准备好了,如何在前台更好地展示嘞?
百度Echarts图表:可以参考百度开源的绘图JS组件Echarts组件这篇博客,心理有个大概。
三: 具体实现:前台数据展示
0.基本实现:利用百度Echarts组件展示后台数据
目前的问题是,前端工程师已经把前台界面做好了,我们也已经将前端开发的界面加入到了工程中,如何把后台的数据怼上去???
这其中的关键是前后端进行通信!
常见的通信方式是Jquery和Ajax:前端的图表需要 实时的局部刷新 ,所以需要用到Ajax;所以上面说,前后端的通信方式常采用Ajax;
(1)前后台传输数据大多采用JSON格式:所以,在RequestTotalServlet这个Servlet中需要把传递给前台的数据转成JSON格式:
(2)前台的创建的total.html文件:前台和后台通信采用的是Ajax
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="js/echarts.min.js"></script>
<script type="text/javascript" src="js/jquery-3.5.1.min.js"></script>
</head>
<body>
<div id="main" style="width: 600px; height: 400px;"></div>
<script type="text/javascript">
$.ajax({
url:"./rt",
type:"get",
dataType:"json",
success:function(json){
// JavaScript自动将后台传过来的json字符串转成json对象了;
console.log(json.time);
console.log(json.value);
//*****************************************************************//
// 基于准备好的dom,初始化echarts实例
// 获取div对象,利用echarts.init()对获取的div进行初始化;于是就得到了一个myChart图表对象;
var myChart = echarts.init(document.getElementById('main'));
// 指定图表的配置项和数据
var option = {
title : {
text : '请求流量分析统计'
},
tooltip : {},
legend : {
data : [ '访问量' ] //
},
xAxis : {
data : json.time // 不得不佩服JavaScript对JSON良好的支持,很给力!!!
},
yAxis : {}, // y轴没有设置,表示显示对应的数值;;;数值就在下面的series中定义;
series : [ {
name : '访问量', // 这个需要和上面legend中的data的名称保持对应;
type : 'line', // 代表柱状图
data :json.value
} ]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option); // 激活刚才在option的设置项
//*****************************************************************//
}
})
</script>
</body>
</html>
效果:
1.完善一:图表自动刷新
但是,现在的有一个问题:图表不能自动刷新,而是需要我们手动刷新total.html页面才能实时展现最新数据:如何做?
可以每一秒向服务器查询一次数据: 需要使用JavaScript定时器 来实现:
total.html做如下更改:(1)将原先<script>中的内容转移到了showChart()方法中;(2)window.setInterval(“showChart()“,1000); :每1秒执行一下showChart()方法;(3)也就是每一秒中发送一个/rt请求,去获取最新的访问次数;
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="js/echarts.min.js"></script>
<script type="text/javascript" src="js/jquery-3.5.1.min.js"></script>
</head>
<body>
<div id="main" style="width: 600px; height: 400px;"></div>
<script type="text/javascript">
function showChart(){
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
$.ajax({
url:"./rt",
type:"get",
dataType:"json",
success:function(json){
// JavaScript自动将后台传过来的json字符串转成json对象了;
console.log(json.time);
console.log(json.value);
//*****************************************************************//
// 基于准备好的dom,初始化echarts实例
// 获取div对象,利用echarts.init()对获取的div进行初始化;于是就得到了一个myChart图表对象;
var myChart = echarts.init(document.getElementById('main'));
// 指定图表的配置项和数据
var option = {
title : {
text : '请求流量分析统计'
},
tooltip : {},
legend : {
data : [ '访问量' ] //
},
xAxis : {
data : json.time // 不得不佩服JavaScript对JSON良好的支持,很给力!!!
},
yAxis : {}, // y轴没有设置,表示显示对应的数值;;;数值就在下面的series中定义;
series : [ {
name : '访问量', // 这个需要和上面legend中的data的名称保持对应;
type : 'line', // 代表柱状图
data :json.value
} ]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option); // 激活刚才在option的设置项
//*****************************************************************//
}
})
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
}
window.setInterval("showChart()",1000);
</script>
</body>
</html>
效果:发现,这个图表每隔1秒钟就刷新一下;;但是,通过浏览total.html内容发现,访问/rt请求,这个请求也会被监听器拦截到,所以访问/rt的请求也会被计算上;
所以,为了避免上述请求,需要把/rt这个请求排除在外,即访问/rt不应该计入请求次数的增减:
2.完善二:监听器中设置一下,以在业务上实现过滤某些请求
需要在监听器中设置一下:
效果:发现,访问/rt不再看成增加访问次数了;