监听器Listener+百度Echarts实现请求流量分析统计

62 篇文章 3 订阅
3 篇文章 1 订阅

监听器Listener+百度Echarts实现请求流量分析统计

之前学习的过滤器,过滤器是针对于请求过滤。而今天我们要学习的监听器,就像汽车的自动刹停技术,监听汽车与前方物体的距离,从而采取措施。JavaWeb中的监听器也是如此,监听事物变化,从而采取措施。

  • 监听器(Listener)是J2EE Servlet模块下的组件
  • Listener的作用对Web应用对象的行为进行监控
  • 通过Listener监听Web应用对象功能状态的变化,自动触发指定的功能代码

三种监听对象

  • ServletContext-对全局ServletContext及其属性进行监听
  • HttpSession-对用户会话及其属性操作进行监听
  • ServletRequest-对请求及属性操作进行监听

过滤器与监听器的区别

  • 过滤器(Filter)的职责是对URL进行过滤拦截,是主动的执行
  • 监听器(Listener)的职责是对Web对象进行监听,是被动触发

开发监听器三要素

  1. 实现XxxListener接口,不同接口对应不同监听对象
  2. 实现每个接口中独有的方法,实现触发监听的后续操作
  3. 在web.xml中配置<listener>使监听器生效

案例:实现ServletContextListener接口演示一个简单监听器案例

FirstListener.java

package listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
//注解形式
//@WebListener
public class FirstListener implements ServletContextListener{

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		// TODO Auto-generated method stub
		System.out.print("ServletContext已销毁");
	}

	@Override
	public void contextInitialized(ServletContextEvent sce) {
		// TODO Auto-generated method stub
		System.out.print("ServletContext已初始化");
	}

}

推荐使用web.xml配置的形式而不是注解引入监听器,因为listener往往是应用程序全局的监听操作,对于这种全局的应用方式最好使用web.xml配置的方式

web.xml

  <listener>
  	<listener-class>listener.FirstListener</listener-class>
  </listener>

内置对象监听器

监听器的实现需要实现监听器接口,每种监听器接口对应不同的监听器对象。6种常用监听接口:
内置对象监听器接口:

ServletContextListener - 监听ServletContext对象创建、销毁等操作
HttpSessionListener - 监听HttpSession对象创建、销毁等操作
ServletRequestListener - 监听HttpServletRequest对象创建、销毁

HelloServlet.java

package listener;

import java.io.IOException;
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 HelloServlet
 */
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public HelloServlet() {
        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
		response.getWriter().println("Hello World");
		//在request这3个对象中各存放3个自定义属性,方便属性监听器的使用
		request.getServletContext().setAttribute("sc-attr1","sc-attr-value1");
		request.getSession().setAttribute("session-attr1", "session-attr-value1");
		request.setAttribute("request-attr1", "request-attr-value1");
	}

	/**
	 * @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);
	}

}

WebListener.java

package listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class WebListener implements ServletContextListener, HttpSessionListener, ServletRequestListener {

	@Override
	public void requestDestroyed(ServletRequestEvent arg0) {
		// TODO Auto-generated method stub
		System.out.println("HttpServletRequest已被销毁");
	}

	@Override
	public void requestInitialized(ServletRequestEvent sre) {
		// TODO Auto-generated method stub
		HttpServletRequest request = (HttpServletRequest)sre.getServletRequest();
		System.out.println("HttpServletRequest已被创建,URI:"+request.getRequestURI());
	}

	@Override
	public void sessionCreated(HttpSessionEvent se) {
		// TODO Auto-generated method stub
		HttpSession session = se.getSession();
		System.out.println("Session已被创建,SessionId:"+session.getId());
	}

	@Override
	public void sessionDestroyed(HttpSessionEvent arg0) {
		// TODO Auto-generated method stub
		System.out.println("Session已被销毁");
	}

	@Override
	public void contextDestroyed(ServletContextEvent arg0) {
		// TODO Auto-generated method stub
		System.out.println("ServletContext已销毁");
	}

	@Override
	public void contextInitialized(ServletContextEvent arg0) {
		// TODO Auto-generated method stub
		System.out.println("ServletContext已初始化");
	}

}

web.xml完成配置即可

web应用程序执行过程

发起一个请求时 tomcat处理的过程:Web应用启动时,ServletContext被初始化,启动成功后访问地址时,一个HttpServletRequest对象被创建。同时因为是一个新的浏览器窗口,所以tomcat会创建一个session对象,网页处理完成后HttpServletRequest被销毁。
第二次请求(当浏览器窗口刷新后),session 并没有被创建,因为session id 已存在,通过确认session id 的存在,所以并不会创建新的session。此时,HttpServletRequest 又经历了一次创建与销毁的过程。
当浏览器关闭重新打开一个新的窗口,再次访问这个网址,这时一个新的session被创建。原因是新的浏览器并没有包含任何session id,所以由新的浏览器窗口向tomcat发送请求后,会为其创建一个对应的session,原有的session并不会消失,只是原有的sessionid的凭证不存在了,30分钟后自然过期,或程序代码人为关闭。
当关闭应用时,ServletContext 才被销毁。

属性监听接口(用的不多,了解)

  • ServletContextAttributeListener - 监听全局属性操作
  • HttpSessionAttributeListener - 监听用户会话属性操作
  • ServletRequestAttributeListener - 监听请求属性操作

WebAttributeListener.java

public class WebAttributeListener implements ServletContextAttributeListener,HttpSessionAttributeListener ,ServletRequestAttributeListener{

	@Override
	public void attributeAdded(ServletContextAttributeEvent event) {
		System.out.println("ServletContext新增属性:" + event.getName() + "->" + event.getValue());
	}

	@Override
	public void attributeRemoved(ServletContextAttributeEvent event) {
		
	}

	@Override
	public void attributeReplaced(ServletContextAttributeEvent event) {

	}

	@Override
	public void attributeAdded(HttpSessionBindingEvent event) {
		System.out.println("HttpSession新增属性:" + event.getName() + "->" + event.getValue());
	}

	@Override
	public void attributeRemoved(HttpSessionBindingEvent event) {
		
	}

	@Override
	public void attributeReplaced(HttpSessionBindingEvent event) {

	}

	@Override
	public void attributeAdded(ServletRequestAttributeEvent srae) {
		System.out.println("Request新增属性:" + srae.getName() + "->" + srae.getValue());		
	}

	@Override
	public void attributeRemoved(ServletRequestAttributeEvent srae) {
		
	}

	@Override
	public void attributeReplaced(ServletRequestAttributeEvent srae) {
		
	}

}

监听器的应用场景

案例:请求流量分析

echarts:https://echarts.apache.org/zh/tutorial.html
用到了echarts.min.js、jquery-3.6.0.min.js、fastjson-1.2.53.jar
在这里插入图片描述
监听器RequestTotalListener.java

package 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;
import javax.servlet.http.HttpServletRequest;

public class RequestTotalListener implements ServletContextListener, ServletRequestListener {

	@Override
	public void requestDestroyed(ServletRequestEvent sre) {
		// TODO Auto-generated method stub

	}

	@Override
	public void requestInitialized(ServletRequestEvent sre) {
		// TODO Auto-generated method stub
		//将"/rt"这个url排除在外
		HttpServletRequest request = (HttpServletRequest)sre.getServletRequest();
		String url = request.getRequestURL().toString();
		if(url.endsWith("/rt")==true) {
			return;
		}
		//先取出存放在全局对象中的时间和次数数据
		//TimeList: 10:02  10:03  10:04   10:05
		//ValueList:  5       7      10     2
		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);
		if(timeList.indexOf(time)==-1) {
			timeList.add(time);
			valueList.add(1);
			sre.getServletContext().setAttribute("timeList", timeList);
			sre.getServletContext().setAttribute("valueList", valueList);
		}else {
			int index = timeList.indexOf(time);
			int value = valueList.get(index);
			valueList.set(index, value+1);
			sre.getServletContext().setAttribute("valueList", valueList);
		}
	}

	@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();
		sce.getServletContext().setAttribute("timeList", timeList);
		sce.getServletContext().setAttribute("valueList", valueList);
	}

}

RequestTotalServlet.java进行与前台的数据通信

package total;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
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 com.alibaba.fastjson.JSON;

/**
 * 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
		ServletContext context = request.getServletContext();
		List<String> timeList = (List)context.getAttribute("timeList");
		List<Integer> valueList = (List)context.getAttribute("valueList");
		response.setContentType("text/html;charset=utf-8");
//		response.getWriter().println(timeList.toString()+"<br/>");
//		response.getWriter().println(valueList.toString());
	
		Map result = new HashMap();
		result.put("timeList",timeList);
		result.put("valueList",valueList);
		String json = JSON.toJSONString(result);
		response.getWriter().println(json);
	}

	/**
	 * @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);
	}

}

total.html图表展示页面

<!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.6.0.min.js"></script>
</head>
<body>
    <!-- 为ECharts准备一个具备大小(宽高)的Dom -->
    <div id="main" style="width: 600px;height:400px;"></div>
    <script type="text/javascript">
    //编写js定时器不断请求数据实现同步
    	function showChart(){
        	$.ajax({
        		url:"./rt",
        		type:"get",
        		"dataType":"json",
        		success:function(json){
        			console.log(json.timeList);
        			console.log(json.valueList);
        		    // 基于准备好的dom,初始 化echarts实例
        	        var myChart = echarts.init(document.getElementById('main'));

        	        // 指定图表的配置项和数据
        	        var option = {
        	            title: {
        	                text: '请求流量统计分析'
        	            },
        	            tooltip: {},
        	            legend: {
        	                data:['销量']
        	            },
        	            xAxis: {
        	                data: json.timeList
        	            },
        	            yAxis: {},
        	            series: [{
        	                name: '访问量',
        	                type: 'line',
        	                data: json.valueList
        	            }]
        	        };

        	        // 使用刚指定的配置项和数据显示图表。
        	        myChart.setOption(option);
        		}
        	})
    	}
		window.setInterval("showChart()",1000);	//每秒刷新
    
    </script>
</body>
</html>

test1.html写一些网站测试页面

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>test1</h1>
</body>
</html>

案例:静态数据预处理

对于一些长期不会改变的数据,可以在服务器每次启动的时候利用上下文监听器在全局属性中写入。可以避免每次加载页面时都要从数据库获取数据

使用jstl两个jar包taglibs-standard-impl-1.2.5.jar和taglibs-standard-spec-1.2.5.jar

在程序启动时添加全局静态频道和url

静态数据监听器StaticDataListener.java

public class StaticDataListener implements ServletContextListener{

	@Override
	public void contextInitialized(ServletContextEvent sce) {
		List list  = new ArrayList();
		list.add(new Channel("Java" , "my Java"));
		list.add(new Channel("UI" , "my UI"));
		list.add(new Channel("Video" , "my Video"));
		sce.getServletContext().setAttribute("channelList", list);
	}

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		
	}

}

Channel.java频道类

public class Channel {
	private String channelName;
	private String url;
	
	public Channel(String channelName, String url) {
		super();
		this.channelName = channelName;
		this.url = url;
	}
	public String getChannelName() {
		return channelName;
	}
	public void setChannelName(String channelName) {
		this.channelName = channelName;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	
}

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!-- 引入jstl -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<c:forEach items="${applicationScope.channelList }" var="c">
	<a href="${c.url }">${c.channelName }</a> | 
</c:forEach>
<hr/>
</body>
</html>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

摘星喵Pro

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值