河南怎么建设网站,搭建网站要多久,北京建设集团网站,建交易网站需要多少钱作者简介#xff1a;大家好#xff0c;我是smart哥#xff0c;前中兴通讯、美团架构师#xff0c;现某互联网公司CTO 联系qq#xff1a;184480602#xff0c;加我进群#xff0c;大家一起学习#xff0c;一起进步#xff0c;一起对抗互联网寒冬 Tomcat三大组件#x…作者简介大家好我是smart哥前中兴通讯、美团架构师现某互联网公司CTO 联系qq184480602加我进群大家一起学习一起进步一起对抗互联网寒冬 Tomcat三大组件Servlet、Listener、Filter今天来简单复习一下Listener。此前如果从来没学习过三大组件的同学可以去B站搜索JavaWeb 崔希凡选择感兴趣的知识点自行复习。 复习Listener
大致来说常用的监听器就是“62”
6个常规监听器|---ServletContext|---ServletContextListener生命周期监听|---ServletContextAttributeListener属性监听|---HttpSession|---HttpSessionListener生命周期监听|---HttpSessionAttributeListener属性监听|---ServletRequest|---ServletRequestListener生命周期监听|---ServletRequestAttributeListener属性监听
2个感知监听|---HttpSessionBindingListener|---HttpSessionActivationListener
感知监听都是Session相关的我已经在《Cookie与Session》一文中讲过这里就不提了。 6个常规监听器分属三类分别对应JavaWeb三大域对象除去JSP的Page域ServletContext、HttpSession、ServletRequest。共三对每一对都包括1个生命周期监听和1个属性监听。
所谓生命周期监听器就是监听三大域对象的创建和销毁。每当Tomcat创建或销毁三大域对象都会被这些监听器察觉然后它们会做相应的操作调用自身的特定方法。 属性监听器则专门监听三大域对象get/setAttribute()。每当我们给域对象设置值或者从里面取值都会被它们监听到然后还是触发它们特定的方法。 先复习一下Servlet如何处理请求 然后我们来看看监听器到底在什么时候做了什么事。
为了帮助大家理解接下来这张图的细节我问几个问题大家带着问题去看
三大生命周期监听器各自在何时创建、销毁顺序是怎么样的访问一个ServletHttpSessionListener一定会触发吗换个角度就是访问ServletSession一定会创建吗三大属性监听何时触发 属性监听没画出来自行脑补 答案 问题一
在项目启动时ServletContextListener监听到ServletContext对象创建每一次请求Tomcat都会创建一个Request它的创建会被ServletRequestListener监听到如果Servlet中调用了request.getSession()则Tomcat会创建Session如果根据JSESSIONID找不到对应的这会被HttpSessionListener监听到请求结束Request销毁被监听到用户30分钟未访问Session过期销毁被监听到项目关停ServletContext销毁被监听到 问题二
只有当在Servlet中调用request.getSession()且根据JSESSIONID找不到对于的Session时才会创建新的Session对象才会被监听到。第二次请求浏览器会带上JSESSIONID此时虽然还是request.getSession()但是会返回上次那个。根据JSESSIONID去Session这个过程是隐式的我们看到的就是getSession()。 问题三
对于图中的步骤7/11/12也就是get/setAttribute()时会触发属性监听。 搞清楚每一种监听器的作用以及触发时机是最重要的使用其实很简单。去看崔老师视频吧讲得很清楚了。 观察者模式
大家觉得Listener难在哪 是监听器种类太多记不清吗不会吧不就是“62”吗。 是各个监听器的触发时机扑朔迷离吗也不会啊上面的图讲得很清楚了。 其实大家觉得监听器难是因为根本不知道为啥它能起作用。监听器的底层原理其实涉及到一种设计模式观察者模式Observer。 先来看监听器的定义
监听器就是一个实现了特定接口的普通Java程序这个程序专门用于监听另一个Java对象的方法调用或者属性改变。当被监听对象发生上述事件后监听器某个方法将立即被执行。 三个概念被监听对象、事件、监听器对象
道理都懂但是还是没讲到点子上。为啥监听器能监听 程序毕竟不是人不像警察盯着小偷看到他偷东西就动手抓人。在我看来一个方法能执行必然是被调用有两种可能
定时任务对象调用/静态方法调用 监听器肯定不是通过定时任务实现的毕竟它的方法调用时机是在“被监听对象特定行为发生时”。既然不是定时任务那么肯定是被监听对象主动告诉监听器的 是不是觉得很荒唐被监听对象主动告诉监听对象那还叫监听器监听个鬼哦... 但是大家有没有想过监听器英文名叫Listener我翻译成“倾听者”有何不可就是说Listener对象一直在侧耳倾听等待被监听对象发号施令。这个翻译骚不骚 也就是说被监听对象发生某个行为时会主动告诉Listener对象方法调用让它执行对应的特定操作 代码结构 被监听对象
// 被监听对象
public class Thief {private ThiefListener listener;public void registerListener(ThiefListener listener) {this.listener listener;}public void steal() {// 偷之前告诉警察if (listener ! null) {Event event new Event(this);// 喂有胆开枪啊listener.shot(event);}// 偷东西System.out.println(to steal money...);}}
监听器接口
// 它的实现类就是监听器对象
public interface ThiefListener {void shot(Event event);
}
事件就是包装后的被监听对象
public class Event {private Thief thief;public Event() {}public Event(Thief thief) {this.thief thief;}public Thief getThief() {return thief;}public void setThief(Thief thief) {this.thief thief;}
}
测试
public class ObserverTest {public static void main(String[] args) {// 被监听对象Thief thief new Thief();// 监听器直接new一个接口的匿名类对象ThiefListener thiefListener new ThiefListener() {public void shot(Event event) {// 我这里并没有用到event实际上可以从event取出事件源System.out.println(啪啪啪);}};// 注册监听thief.registerListener(thiefListener);// 特定行为触发监听器内部调用listener.shot()thief.steal();}
}
作者简介大家好我是smart哥前中兴通讯、美团架构师现某互联网公司CTO 进群大家一起学习一起进步一起对抗互联网寒冬