需求描述

某一个域名所对应的网站在某个时间段,浏览的变化情况:针对波峰和波谷的变化,就可以针对性地对网站进行优化和调整

total1

此案例包括两个部分:利用监听器实现对网站访问的量的获取,图表信息的展示

一.具体实现:后台数据准备

1.第一部分:编写监听器

total2

RequestTotalListener:监听器

  1. 下面这个监听器的编写方式,最重要的启发是:一个问题,梳理清业务后,做好逻辑规划,然后按条例分别编写程序就ok了
  2. 这个监听器内容其实很简单,大略看看就ok了
  3. 全局对象ServletContext创建的时候,就在全局对象中初始化两个集合对象timeList和valueList;每当请求对象ServletRequest被创建的时候,就在timeList和valueList中做出对应的操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class RequestTotalListener implements ServletRequestListener, ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent ser) {
//应用程序启动的时候,初始化需要存储的数据
List timeList = new ArrayList<>(); //存储时间的集合对象
List valueList = new ArrayList<>(); //具体时间的访问量数据的集合对象、
//获取ServletContext对象,并将存储时间和访问量的值存储到这个对象中
//即每次启动应用,在ServletContext全局对象中初始化这两个可以存储时间和访问量的属性
ser.getServletContext().setAttribute("timeList",timeList);
ser.getServletContext().setAttribute("valueList",valueList);
}

@Override
public void contextDestroyed(ServletContextEvent ser) {

}

@Override
public void requestDestroyed(ServletRequestEvent ser) {

}

@Override
public void requestInitialized(ServletRequestEvent ser) {
//TimeList: 10:01 10:02 10:05 先确定时间是否存在
//ValueList: 3 6 10 这两个List中的值通过索引值精准对应;
List<String> timeList =(List) ser.getServletContext().getAttribute("timeList");//获取到ServletContextInit初始化后创建的集合的value值
List<Integer> valueList =(List) ser.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);//给value值添加默认的值1
ser.getServletContext().setAttribute("timeList",timeList);
ser.getServletContext().setAttribute("valueList",valueList);
}else {
//获取当前时间在timeList中的索引,在valueList相同索引处的值+1
//timeList和valueList,通过索引值的顺序一一对应
int index = timeList.indexOf(time);
int value = valueList.get(index);
ser.getServletContext().setAttribute("timeList",timeList);
ser.getServletContext().setAttribute("valueList",valueList);

}
}
}

配置监听器

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<listener>
<listener-class>RequestTotalListener</listener-class>
</listener>
</web-app>

2.第二部分:添加HTML页面

为了模拟这个应用,添加几个HTML页面以供访问

total3

3.第三部分:编写Servlet:RequestTotalServlet

这个Servlet的作用是,获取全局对象ServletContext中的timeList和valueList;并将其添加到响应中去;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.List;

@WebServlet(name = "RequestTotalServlet", value = "/request")
public class RequestTotalServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<String> timeList = (List)request.getServletContext().getAttribute("timeList");//增加一个集合对象获取到ServletContext中的属性
List<String> 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());
}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}
}

4.第四部分:效果展示

totaal4

至此,后台数据部分已经准备完成,启动应用,在浏览器对几个html访问几次(其实访问RequesTotalServlet也是可以,都会有ServletRequest对象创建)

二.如何让数据在前台展示更美观

百度的Echarts图表:

1.Echarts简单使用范例

直接百度echarts:这是百度自己研发的一款图表组件,这个组件目前可以说是最强大的一款图表JS框架,echarts已经被Apache收购了

total5

进入文档部分,并点击使用教程部分

total6

total7

其次,将下载的文件导入到项目中

解压后,找到:echarts.min.js这个js文件(在dist目录下)

total8

将Echarts组件的JS文件,添加到项目中:需要将这个文件放到Web目录下;一般会在Web目录下新建一个文件夹欸,专门存放外部引入的JS文件

total9

编写范例

根据官网的教程:total.html内容如下

  1. 第一步:引入Echarts:>
  2. 第二步:为了Echarts准备一个具有高宽的DOM容器,
  3. 第三步:设置图表:先定义图片表,然后再option中设置图表中的各种属性,最后将设置项激活
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>total</title>
<script type="text/javascript" src="JS/echarts.min.js"></script>
</head>
<body>
<div id="main" style="width: 600px;height: 400px;"></div>
<script type="text/javascript">
//基于准备好的dom,初始化echarts实例
//获取div对象,利用echarts.init()对获取的div进行初始化;于是就得到一个myChart图表对象
var myChart = echarts.init(document.getElementById('main'));

//指定图表的配置和数据

// 指定图表的配置项和数据
var option = {
title: {
text: 'ECharts 入门示例'
},
tooltip: {},
legend: {
data: ['销量']
},
xAxis: {
data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
},
yAxis: {},
series: [
{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}
]
};

// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
</script>
</body>
</html>

最后观察效果

启动应用:访问total.html

total10

2.Echarats补充

其实,Echarts功能十分强大,有需要的时候,可以多参考官网和案例

total11

三:具体实现:前台数据展示

0.基本实现:利用百度Echarts组件展示后台数据

目前的问题是,前端工程师已经把前台的界面做好了,我们也已经将前端开发的界面加到工程总,如何把后台的数据怼上去呢

这其中的关键是前后端的通信

常见的通信方式是Jquery和Ajax:前端的图表需要实时的局部刷新,所以需要用到Ajax;所以上面说,前后端的通信方式采用Ajax

1.前后台传输数据采用JSON格式

在RequestTotalServlet这个Servlet中需要把传递给前台的数据转成JSON格式,使用前需要注意的是引入fastJson的jar包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import com.alibaba.fastjson.JSON;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@WebServlet(name = "RequestTotalServlet", value = "/request")
public class RequestTotalServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<String> timeList = (List)request.getServletContext().getAttribute("timeList");//增加一个集合对象获取到ServletContext中的属性
List<String> 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());
//将timeList,valueList存放到HashMap集合中,做key值与value值
Map result = new HashMap();
result.put("time",timeList);
result.put("value",valueList);

//将集合Map转换成JSON字符串,然后回显到前台数据中
String jsonRequest = JSON.toJSONString(result);
response.getWriter().println(jsonRequest);

}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}
}

2.创建total1.html文件:客户端和后台的通信采用Ajax

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>total1</title>
<script type="text/javascript" src="JS/echarts.min.js"></script>
<script type="text/javascript" src="JS/jquery-3.6.0.js"></script>
</head>
<body>
<div id="main" style="width: 600px;height: 400px"></div>
<script type="text/javascript">
$.ajax({
url:"./request",
type:"get",
dataType:"json",
success:function (json){
//Ajax已经将JSON字符串转化为JSON对象,自动将后台传过来的json字符串转为JSON对象
console.log(json.time);//在控制台中输出JSON对象调用的time(key)
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
},
yAxis: {}, //y轴没有设置,表示显示对应的数值;数值就在下面的series中定义
series: [
{
name: '访问量', //这个需要和上面的legend中的data的名称保持对应
type: 'line', //代表线状图
data: json.value //JSON对象调用集合中的value(value)
}]
};
//使用刚指定的配置项和数据显示图表
myChart.setOption(option); //激活刚才在option的设置项
}
})
</script>
</body>
</html>

效果展示:

total12

四:完善项目

1.图表自动刷新

但是,现在的问题:图表不能自动刷新,而是需要我们手动刷新toal1.html页面才能实时展现最新的数据

可以每一秒向服务器查询一次数据:需要使用JavaScript定时器来实现:

total1.html做如下的更改:(1)将原先的