前言

    监听器(Listener)就是监听对象的创建、销毁等状态的变化以及定义一些事件发生后接下来要进行的动作;主要监听的三个域对象为:ServletRequest域、HttpSession域 和ServletContext域
    在目前的Servlet API中提供的web事件监听器接口有如下所示的几个:

1.ServletContextListener -- 监听servletContext对象的创建以及销毁
    1.1    contextInitialized(ServletContextEvent arg0)   -- 创建时执行
    1.2    contextDestroyed(ServletContextEvent arg0)  -- 销毁时执行
    
2.HttpSessionListener  -- 监听session对象的创建以及销毁
    2.2   sessionCreated(HttpSessionEvent se)   -- 创建时执行
    2.2   sessionDestroyed(HttpSessionEvent se) -- 销毁时执行

3.ServletRequestListener -- 监听request对象的创建以及销毁
    3.1    requestInitialized(ServletRequestEvent sre) -- 创建时执行
    3.2    requestDestroyed(ServletRequestEvent sre) -- 销毁时执行

4.ServletContextAttributeListener  -- 监听servletContext对象中属性的改变
    4.1    attributeAdded(ServletContextAttributeEvent event) -- 添加属性时执行
    4.2    attributeReplaced(ServletContextAttributeEvent event) -- 修改属性时执行
    4.3    attributeRemoved(ServletContextAttributeEvent event) -- 删除属性时执行

5.HttpSessionAttributeListener  --监听session对象中属性的改变
    5.1    attributeAdded(HttpSessionBindingEvent event) -- 添加属性时执行
    5.2    attributeReplaced(HttpSessionBindingEvent event) -- 修改属性时执行
    5.3    attributeRemoved(HttpSessionBindingEvent event) -- 删除属性时执行

6.ServletRequestAttributeListener  --监听request对象中属性的改变
    6.1    attributeAdded(ServletRequestAttributeEvent srae) -- 添加属性时执行
    6.2    attributeReplaced(ServletRequestAttributeEvent srae) -- 修改属性时执行
    6.3    attributeRemoved(ServletRequestAttributeEvent srae) -- 删除属性时执行

参考文章:
1、spring boot入门(八) springboot的监听器Listener。最完整、简单易懂、详细的spring boot教程。 2、Java Web Listener学习笔记 3、Java篇-Listener

1、Listener接口的实现及使用

两步操作即可以实现监听器接口的实现:

  • 自定义一个实现相关Listener接口的类
  • 在启动类中进行相关的容器配置
1.1、ServletContextListener接口的实现
package com.learn.listeners;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@WebListener
public class ContextListener implements ServletContextListener{

	private static final Logger logger=LoggerFactory.getLogger(ContextListener.class);
	@Override
	public void contextInitialized(ServletContextEvent sce) {
		logger.info("初始化一个servletContext......");
	}

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		logger.info("销毁一个servletContext......");
	}
}

配置监听器的容器,有两种方式:
(1)如上述代码中所示,在定义的监听器类上使用 @WebListener 注解,然后在项目的启动类中,加上如下所示内容:

@SpringBootApplication
@ServletComponentScan(basePackages= {"com.learn.listeners"})  // 添加监听器所在的包名
public class LearnSpringbootIpApplication {
		.......
}

(2)在项目的启动类中,使用ServletListenerRegistrationBean来创建Bean,如下所示:

@Bean 
	public ServletListenerRegistrationBean<ContextListener> contextListenerBean() {
		ServletListenerRegistrationBean<ContextListener> contextListenerBean= new ServletListenerRegistrationBean<ContextListener>();
		contextListenerBean.setListener(new ContextListener());
		contextListenerBean.setOrder(1);
		return contextListenerBean;
	}

    在启动web项目时,会执行contextInitialized 初始化的方法,当web项目关闭时会执行销毁的方法。日志记录如下:

springboot监听pg binlog日志_ide

1.2、HttpSessionListener 接口的实现及使用

实现代码:

package com.learn.listeners;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@WebListener
public class SessionListener implements HttpSessionListener {

	private static final Logger logger=LoggerFactory.getLogger(SessionListener.class);
	@Override
	public void sessionCreated(HttpSessionEvent se) {
		
		logger.info("初始化一个sessionListener......");
	}

	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
		logger.info("销毁一个sessionListener......");
	}
}

    实现完成Session监听器以后,配置过程与1.1中介绍的一样,这里就不赘述了;运行项目,当执行的过程中发生Session的创建或销毁时就会触发监听器中相应的代码。

测试代码:

@CrossOrigin
	@RequestMapping(value="/api/v2/session",method=RequestMethod.GET)
	public void destorySession(HttpServletRequest request) {
		HttpSession session=request.getSession();
		session.invalidate();
	}

执行结果:

springboot监听pg binlog日志_监听器_02

1.3、ServletRequestListener 接口的实现及使用
package com.learn.listeners;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@WebListener
public class RequestListener implements ServletRequestListener {
	
	private static final Logger logger=LoggerFactory.getLogger(RequestListener.class);

	@Override
	public void requestDestroyed(ServletRequestEvent sre) {
		logger.info("初始化一个requestListener......");
	}

	@Override
	public void requestInitialized(ServletRequestEvent sre) {
		logger.info("销毁一个requestListener......");
	}
}

    实现完成Session监听器以后,配置过程与1.1中介绍的一样;当项目中有ServletRequest对象的创建或者销毁时就是触发该监听器。

2、自定义事件的发布及监听

关于这块的内容,在网上看到一个不错的文章,参考文章地址:spring 自定义事件发布及监听(简单实例)流程分析:
在一个完整的事件体系中,除了事件和监听器以外,还应该有3个概念;

  1. 事件源:事件的产生者,任何一个event都必须有一个事件源;
  2. 事件广播器:它是事件和事件监听器之间的桥梁,负责把事件通知给事件监听器;
  3. 事件监听器注册表:就是spring框架为所有的监听器提供了一个存放的地方;

通过流程图,可以看出它们是如何各司其职的,如下:

springboot监听pg binlog日志_监听器_03


其实通过流程图,我们很容易发现事件体系就是观察者模式的具体实现,它并没有任何的神秘之处。

结构分析:
1、 事件类(ApplicaitonEvent):目前spring框架本身仅仅提供了几个事件,很多的事件都是需要自定义的。

ApplicationEvent唯一的构造函数是ApplicaitonEvent(Object source),通过source指定事件源。 它有两个子类;

    (1)ApplicationContextEvent:容器事件,也就是说事件源是ApplicationContext,框架提供了四个子类,分别代表容器启动,刷新,停止和关闭事件。

    (2)RequestHandleEvent:这是一个与Web应用相关的事件,当一个请求被处理后,才会产生该事件。

一般来说,我们都是扩展ApplicationEvent来自定义事件。

springboot监听pg binlog日志_java_04


2. 事件监听器接口(ApplicationListener)

所有的监听器都需要实现该接口,该接口只定义了一个方法:onApplicaitonEvent (E event),该方法接收事件对象,在该方法中编写事件的响应处理逻辑。

springboot监听pg binlog日志_监听器_05


    通过一个实例来讲解事件发布和事件监听的过程。这个例子包括一个模拟的邮件发送器MailSender,它在向目的地发送邮件的时候 会产生一个MailSendEvent事件,我们同时向容器中注册了该事件的监听器MailSendListener;

/**
 * 继承了ApplicationContextEvent,就是个容器事件
 */
public class MailSendEvent extends ApplicationContextEvent {
    private String to;  //目的地

    public MailSendEvent(ApplicationContext source, String to) {
        super(source);
        this.to = to;
    }

    public String getTo(){
        return this.to;
    }
}

很明显,这里的source是ApplicationContext容器。我们再定义一个该事件的监听器MailSendListener,如下:

@Component
public class MailSendListener implements ApplicationListener<MailSendEvent>{
    @Override
    public void onApplicationEvent(MailSendEvent mailSendEvent) {
        MailSendEvent event = mailSendEvent;
        System.out.println("向"+ event.getTo()+ "发送了一封邮件");
    }
}

    上述提及到所有的监听器都必须要实现ApplicationListener,这里是个泛型类,指定了该监听器只监听MailSendEvent事件。
OK,那我们现在来触发事件:MailSender,也就是事件源:

@Component("mailSender")
public class MailSender {
    @Autowired
    private ApplicationContext applicationContext;  //容器事件由容器触发

    public void sendMail(String to){
        System.out.println("MailSender开始发送邮件");
        MailSendEvent event = new MailSendEvent(applicationContext,to);
        applicationContext.publishEvent(event);
    }
}

测试代码:

@RestController
public class ListenerController {
	
	@Autowired
	private MailSender mailSender;
	@CrossOrigin
	@RequestMapping(value="/api/v2/listener",method=RequestMethod.GET)
	public void testDefinedListener(HttpServletRequest request) {
		mailSender.sendMail("北京");
	}
}

测试结果:

springboot监听pg binlog日志_java_06