前言
上一篇博客我们学习了过滤器,这次学习的监听器与过滤器作用十分相似,对于过滤器不了解可以先去看看上一篇博客。
传送门:【过滤器入门】学会使用过滤器,为你的web项目添砖加瓦
接下来我们正式开始学习监听器。
什么是监听器?
监听器是一个专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象。
当被监视的对象发生情况时,立即采取相应的行动。监听器其实就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法立即被执行。
对于监听器:
(1)监听器(Listener)是J2EE Servlet模板下的组件。
(2)Listener的作用是对Web应用对象的行为进行监控。
(3)通过Listener监听自动触发指定的功能代码。
上面提到了Listener的作用是对Web应用对象进行监控,他经常监听的三种对象有:
(1)ServletContext:对全局对象ServletContext及属性进行监听。
(2)HttpSession:对用户会话及其属性操作进行监听。
(3)ServletRequest:对请求及属性操作进行监听。
之前也学过过滤器,那么它们的区别是什么呢?
(1)过滤器(Filter)的职责是对URL进行过滤拦截,是主动的执行。
(2)监听器(Listener)的职责是对Web对象进行监听,是被动的触发。
开发一个监听器
开发一个监听器都要经过以下三个步骤:
(1)实现XXXListener接口,不同接口对应不同监听对象。
(2)实现每个接口中独有的方法,实现触发监听的后续操作。
(3)在web.xml中配置使监听器生效。
接下来我们就来开发一个简单的监听器。
我们对全局变量ServletContext进行监听。在实现接口之后我们需要重写里面的两个方法分别是对象初始化时侯和销毁时候调用的。我们给其中先写上简单的打印即可。
public class FirstListener implements ServletContextListener{ @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中对其进行配置。
com.imooc.listener.FirstListener
或者我们也可以使用注解形式进行配置,只需要在实现接口函数的上方写上@WebListener即可。如下:
之后我们启动这个监听器。可以看到在启动Servlet的时候它执行了初始化的那个函数中的代码,进行了初始化。
在我们关闭服务器之后会发现它,执行了销毁代码块中的代码。
内置对象监听器
之前说了监听器经常监听的三种对象有:
(1)ServletContext:对全局对象ServletContext及属性进行监听。
(2)HttpSession:对用户会话及其属性操作进行监听。
(3)ServletRequest:对请求及属性操作进行监听。
在监听器中有专属的内置对象监听接口来对它们进行监听。
其中有三个接口是对它们的对象进行监听的,如下:
(1)ServletContextListener:监听ServletContext对象的创建、销毁等操作。
(2)HttpSessionListener:监听HttpSession对象的创建、销毁等操作。
(3)ServletRequestListener:监听HttpServletRequest对象创建、销毁等
还有三个接口是对他们的属性进行监听的,如下:
(1)ServletContextAttributeListener:监听全局属性操作。
(2)HttpSessionAttributeListener:监听用户会话属性操作。
(3)ServletRequestAttributeListener:监听请求属性操作。
我们在书写监听器的时候如果有需求实现多个监听器接口即可。
案例演示
我们最后来做一个案例,对于请求进行监听。统计出每分钟请求的次数。
写一个监听器,实现对应接口。对请求的url进行分析是不是我们要拦截的url,然后获取当前请求的时间进行记录。如果这个时间存在那么直接给这个时间的次数加1即可。
public class RequestTotalListener implements ServletContextListener, ServletRequestListener{ @Override public void requestDestroyed(ServletRequestEvent sre) { } @Override public void requestInitialized(ServletRequestEvent sre) { HttpServletRequest request = (HttpServletRequest)sre.getServletRequest(); String url = request.getRequestURI().toString(); if(url.endsWith("rt") == true) { return; } // TODO Auto-generated method stub List timeList = (List)sre.getServletContext().getAttribute("timeList"); List 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); } }
在写一个Servlet,监听器监听出来的数据进行统计处理。
@WebServlet("/rt") public class RequestTotalServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext context = request.getServletContext(); List timeList = (List)context.getAttribute("timeList"); List valueList = (List)context.getAttribute("valueList"); response.setContentType("text/html;charset=utf-8"); response.getWriter().println(timeList.toString()); response.getWriter().println(" "); response.getWriter().println(valueList.toString()); } }
输出如下:
监听成功!
结语
与过滤器一样内容比较少,但是用处比较大,也是重点内容。