监听器
监听器入门
监听器介绍
- 监听器(Listener)是J2EE Servlet模块下的组件
- Listener的作用对Web应用对象的行为进行监控
- 通过Listener监听Web应用对象功能状态的变化,自动触发指定的功能代码
三种监听对象
- ServletContext-对全局ServletContext及其属性进行监听
- HttpSession-对用户会话及其属性操作进行监听
- ServletRequest-对请求及属性操作进行监听
过滤器与监听器的区别
- 过滤器(Filter)的职责是对URL进行过滤拦截,是主动的执行
- 监听器(Listener)的职责是对Web对象进行监听,是被动触发
监听器开发
- 实现XxxListener接口,不同接口对应不同监听对象
- 实现每个接口中独有的方法,实现触发监听的后续操作
- 在web.xml中配置<listener>使监听器生效
/**
* 针对ServletContext对象进行监听,不同接口对应不同监听对象
**/
//@WebListener
//只要这个注解就可以了,无需其他的属性。更推荐使用配置的形式
public class FirstListener implements ServletContextListener{
//因为ServletContext在Web应用启动时创建,所以该监听器在应用启动的时候就进行监听
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext已初始化");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext已销毁");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>first-listener</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<listener>
<listener-class>com.dodoke.listener.FirstListener</listener-class>
</listener>
</web-app>
对象监听器与属性监听器
监听器的实现需要实现监听器接口,每种监听器接口对应不同的监听器对象。其实在监听器中存在六种监听器接口:
内置对象监听器接口
- ServletContextListener - 监听ServletContext对象创建、销毁等操作
- HttpSessionListener - 监听HttpSession对象创建、销毁等操作
- ServletRequestListener - 监听HttpServletRequest对象创建、销毁
属性监听接口
- ServletContextAttributeListener - 监听全局属性操作
- HttpSessionAttributeListener- 监听用户会话属性操作
- ServletRequestAttributeListener- 监听请求属性操作
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public HelloServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().println("Hello World!");
//在ServletContext,HttpSession,HttpServletRequest对象中添加删除属性
request.getServletContext().setAttribute("sc-attr1", "sc-attr-value1");
request.getServletContext().removeAttribute("sc-attr1");
request.getSession().setAttribute("session-attr1", "session-attr-value1");
request.setAttribute("request-attr1", "request-attr-value1");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
public class WebAttributeListener implements ServletContextAttributeListener,HttpSessionAttributeListener ,ServletRequestAttributeListener{
@Override
public void attributeAdded(ServletContextAttributeEvent event) {
System.out.println("ServletContext新增属性:" + event.getName() + "->" + event.getValue());
}
@Override
public void attributeRemoved(ServletContextAttributeEvent event) {
}
@Override
public void attributeReplaced(ServletContextAttributeEvent event) {
}
@Override
public void attributeAdded(HttpSessionBindingEvent event) {
System.out.println("HttpSession新增属性:" + event.getName() + "->" + event.getValue());
}
@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
}
@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
}
@Override
public void attributeAdded(ServletRequestAttributeEvent srae) {
System.out.println("Request新增属性:" + srae.getName() + "->" + srae.getValue());
}
@Override
public void attributeRemoved(ServletRequestAttributeEvent srae) {
}
@Override
public void attributeReplaced(ServletRequestAttributeEvent srae) {
}
}
public class WebListener implements ServletContextListener,HttpSessionListener,ServletRequestListener{
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext已初始化");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext已被销毁");
}
@Override
public void sessionCreated(HttpSessionEvent se) {
HttpSession session = se.getSession();
System.out.println("Session已被创建,SessionId:" + session.getId());
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("Session已被销毁");
}
@Override
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println("HttpServletRequest已被销毁");
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
HttpServletRequest request = (HttpServletRequest)sre.getServletRequest();
System.out.println("HttpServletRequest已被创建,URI:" + request.getRequestURI());
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>listener-interface</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<listener>
<listener-class>com.dodoke.listener.WebListener</listener-class>
</listener>
<listener>
<listener-class>com.dodoke.listener.WebAttributeListener</listener-class>
</listener>
</web-app>
web应用程序执行过程
- 一个请求时 tomcat处理的过程:Web应用启动时,ServletContext被初始化,启动成功后访问地址时,一个HttpServletRequest对象被创建。同时因为是一个新的浏览器窗口,所以tomcat会创建一个session对象,网页处理完成后HttpServletRequest被销毁。
- 第二次请求(当浏览器窗口刷新后),session 并没有被创建,因为session id 已存在,通过确认session id 的存在,所以并不会创建新的session。此时,HttpServletRequest 又经历了一次创建与销毁的过程。
- 当浏览器关闭重新打开一个新的窗口,再次访问这个网址,这时一个新的session被创建。原因是新的浏览器并没有包含任何session id,所以由新的浏览器窗口向tomcat发送请求后,会为其创建一个对应的session,原有的session并不会消失,只是原有的sessionid的凭证不存在了,30分钟后自然过期,或程序代码人为关闭。
- 当关闭应用时,ServletContext 才被销毁。