---
# System prepended metadata

title: Listener監聽器
tags: [Java Web-mvc]

---

# Listener監聽器
###### tags: `Java Web-mvc`

### 1.觀察者模式
![](https://i.imgur.com/6ZLxE3X.png)
    观察者：监控『被观察者』的行为，一旦发现『被观察者』触发了事件，就会调用事先准备好的方法执行操作。
    被观察者：『被观察者』一旦触发了被监控的事件，就会被『观察者』发现。
    
### 2.監聽器簡介
專門用來對其他對象身上發生的事件或狀態改變進行監聽和相應處理的對象，當被監視的對象發生情況時，立即採取相應的動作。

例如：Servlet監聽器：
Servlet規範中定義的一種特殊類，它用於監聽Web應用程序中的ServletContext，HttpSession 和HttpServletRequest等域對象的創建與銷毀事件，以及監聽這些域對象中的屬性發生修改的事件。

### 3.監聽器圖解
![](https://i.imgur.com/SgcLXU7.png)

![](https://i.imgur.com/rsbQ9ZF.png)

### 4.監聽器類型
    1)ServletContextListener-監聽ServletContext對象的產生和銷毀的過程
    2)HttpSessionListener-監聽HttpSession對象的產生和銷毀的過程
    3)ServletRequestListener-監聽ServletRequest對象的產生和銷毀的過程

    4)ServletContextAttributeListener-監聽ServletContext的保存作用域的改動(add、remove、replace)
    5)HttpSessionAttributeListener-監聽HttpSession的保存作用域的改動(add、remove、replace)
    6)ServletRequestAttributeListener-監聽ServletRequest的保存作用域的改動(add、remove、replace)

    7)HttpSessionBindingListener-監聽某個對象在Session域中的創建與移除
    8)HttpSessionActivationListener-監聽某個對象在Session域中的序列化與反序列化

### 5.監聽器具體使用
#### (1)創建監聽器類
```java=
//ServletContextListener是針對ServletContext的監聽
//@WebListener
public class MyServletContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("Servlet上下文對象初始化的動作被我監聽到了");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("Servlet上下文對象銷毀的動作被我監聽到了");
    }
}
```

#### (2)註冊監聽器
法一：可在監聽器類直接註解 @WebListener

法二：在web.xml文件註冊
```xml=
<listener>
    <listener-class>com.atguigu.listener.MyServletContextListener</listener-class>
</listener>
```

### 6.監聽器應用
#### 監聽器
```java=
//監聽上下文啟動，在上下文啟動的時候去創建IOC容器，然後將其保存到application作用域
//後面中央控制器再從application作用域中去獲取IOC容器
@WebListener
public class ContextLoadListener implements ServletContextListener {
    private ServletContextEvent servletContextEvent;

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        //1.獲取ServletContext對象
        ServletContext application = servletContextEvent.getServletContext();
        //2.獲取上下文的初始化參數
        String path = application.getInitParameter("contextConfigLocation");
        //3.創建IOC容器
        BeanFactory beanFactory = new ClassPathXmlApplicationContext(path);
        //4.將IOC容器保存到application作用域
        //因為是ServletContextListener，所以在啟動時，即會執行，創建beanFactory對象
        //若其他程式需要調用beanFactory，就會從application的作用域調用
        application.setAttribute("beanFactory",beanFactory);
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
}
```
#### 監聽器的應用場景
由於是使用ServletContextListener的監聽器，所以是監聽ServletContext

ServletContext是當web執行時，就會自動創建的容器，供所有客戶端共同使用，並且在web結束時銷毀

因此ServletContextListener只要在web執行，ServletContext生成後就會持續監聽它
```java=
    public BeanFactory beanFactory;

    public DispatcherServlet(){
    }

    public void init() throws ServletException {
        super.init();
        //之前是在此處主動創建IOC容器
        //現在優化為從application作用域去獲取
//        beanFactory = new ClassPathXmlApplicationContext();
        ServletContext application = getServletContext();
        //在作用域獲取beanFactory
        //而這個作用域中的對象是在容器啟動時就創建
        Object beanFactoryObj = application.getAttribute("beanFactory");
        if(beanFactoryObj != null){
            beanFactory = (BeanFactory)beanFactoryObj;
        }else{
            throw new RuntimeException("IOC容器創建獲取失敗");
        }
    }
```