Listenner是什么
listenner顾名思义监听器,javaweb中的listenner旨在监听servlet容器中各个对象
的状态变化
这其中的各个对象主要包含三个对象
- servletContext servlet应用上下文对象
- session 用户session对象
- servletRequest http请求对象
状态变化主要包含两种情况
- 对象的创建与销毁
- 对象属性的增加删除和替换
其中各个对象的各个状态变化的接口如下
ServletContext | Session | ServletRequest | |
---|---|---|---|
对象的创建和销毁 | ServletContextListener | HttpSessionListener | ServletRequestListener |
对象那个属性的增加删除和替换 | ServletContextAttributeListener | HttpSessionAttributeListener | ServletRequestAttributeListener |
如何实现一个Listenner
我们以ServletContext为例子,实现ServletContext对象的创建和销毁,实现ServletContext属性的添加删除和更新,其他的对象跟这个类似
实现ServletContextListener
- 实现ServletContextListener接口,
- 实现 创建对象方法(contextInitialized),对象销毁方法(contextDestroyed)
- 加入注解@WebListener
@WebListener
public class MyServletContextListenner implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("contextInitialized");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("contextDestroyed");
}
}
实现ServletContextAttributeListener
- 实现ServletContextAttributeListener接口
- 实现 新增删除更新方法
- 加入注解@WebListener
@WebListener
public class MyServletContextAttributeLisener implements ServletContextAttributeListener {
@Override
public void attributeAdded(ServletContextAttributeEvent scae) {
System.out.println("servletContext attributeAdded");
}
@Override
public void attributeRemoved(ServletContextAttributeEvent scae) {
System.out.println("servletContext attributeRemoved");
}
@Override
public void attributeReplaced(ServletContextAttributeEvent scae) {
System.out.println("servletContext attributeReplaced");
}
}
启动应用
启动应用,发送一个请求,关闭应用,可以看到已经对对应的事件进行了回调
Listenner有什么用
listenner的作用主要在于对各种事件的回调,当某件事件触发后,我们可以对其进行自定义的业务逻辑处理,比如Springmvc框架中,会有ContextLoaderListener这么一个实现,它会监听contextInitialized
的调用,并在调用中初始化spring的上下文WebApplicationContext,初始化完成之后会将这个上下文对象存放到ServletContext的属性中,以便于在后续通过ServletContext来获取这个对象,同时也会监听contextDestroyed
这个方法,以便于在servlet被销毁时,可以关闭spring容器,关闭各种连接,执行销毁逻辑等等,后续会专门写一篇关于Springmvc初始化和销毁的文章,这里就点到为止
观察者模式
Listenner是观察者模式的典型实现,当对象之间存在一对多关系,并且存在行为影响关系时,则可以使用观察者模式
观察者模式中主要设计到两个概念,目标主题和观察者,,观察者订阅主题的消息,当主题行为改变发布消息时,会自动触发观察者的回调,下面我们基于JDK自带的Observer 来实现观察者模式
JDK自带的主题抽象
jdk自带的Observable对象,主要属性changed表示当前是否发生改变,obs表示当前观察者列表,notifyObservers方法用来通知观察者当前已经发生变化
public class Observable {
private boolean changed = false;
private Vector<Observer> obs;
public Observable() {
obs = new Vector<>();
}
public synchronized void addObserver(Observer o);
public void notifyObservers();
}
Observer则是观察者的抽象,只有一个update方法,用来做通知回调,也就是说当Observable调用notifyObservers方法后,将调用Observer的update方法
public interface Observer {
/**
* This method is called whenever the observed object is changed. An
* application calls an <tt>Observable</tt> object's
* <code>notifyObservers</code> method to have all the object's
* observers notified of the change.
*
* @param o the observable object.
* @param arg an argument passed to the <code>notifyObservers</code>
* method.
*/
void update(Observable o, Object arg);
}
上面两个类只是JDK提供给我的抽象,具体的实现还需要我们根据自己的场景来设计
实现一个主题对象,主要继承Observable,在notice方法中,主要是调用了Observable的setChanged,修改changed属性为true,表示当前有改动,紧接着调用notifyObservers用来通知所有观察者
public class Publish extends Observable {
public void notice() {
System.out.println("publish 发送了通知");
setChanged(); //设置changed状态为true
notifyObservers(); //调用父类Observable方法,通知所有观察者
}
}
实现一个观察者SubScribe,实现Observer接口,实现update方法,主要看是否有对应回调
public class SubScribe implements Observer {
private Integer no;
public SubScribe(Integer no) {
this.no=no;
}
@Override
public void update(Observable o, Object arg) {
System.out.println("观察者"+no+"收到了通知");
}
}
新建一个主题对象,并且添加两个观察者,最后主题对象发布通知
public static void main(String[] args) {
Publish publish = new Publish();
SubScribe subscribe1 = new SubScribe(1);
SubScribe subscribe2 = new SubScribe(2);
publish.addObserver(subscribe1);
publish.addObserver(subscribe2);
publish.notice();
}
结果
publish 发送了通知
观察者2收到了通知
观察者1收到了通知