Servlet监听器

瘦欲@ 提交于 2020-10-28 10:35:37

Servlet监听器

一、简介

  1. 监听器的主要功能是负责监听web的各种操作,和js中的事件监听性质一样,当相关事件触发后将产生事件,并对此事件进行处理,在web中可以对对象application(servletContext)、session、request操作进行监听处理。

二、对application对象监听

  • 对application监听,实际上就是对ServletContext监听,主要使用ServletContextListener和ServletContextAttributeeListener两个接口。
application状态监听:ServletContextListener接口
  1. ServletContextListener接口定义的方法:
NO 方法 描述
1 public void contextInitialized(ServletContextEvent sce) 容器启动时触发
2 public void contextDestroyed(ServletContextEvent sce) 容器销毁时触发
在以上状态监听操作中,一旦触发ServletContextListener接口定义的方法,可以通过ServletContextEvent进行事件的处理,此事件定义的方法如下:
NO 方法 描述
1 public ServletContext getServletContext() 取得ServletContext对象
可以通过getServletContext()方法来获取ServletContext对象的实例:
  • 创建ServletContextListener接口实现类
package taeyeon.com.servlet;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

/**
 * application的状态监听
 */
public class StateApplicationListener implements ServletContextListener {
        @Override
        public void contextInitialized(ServletContextEvent sce) {
                System.out.println("容器初始化----->"+sce.getServletContext().getRealPath("/"));//根据指定的虚拟路径返回其真实路径
        }

        @Override
        public void contextDestroyed(ServletContextEvent sce) {
                System.out.println("容器销毁----->"+sce.getServletContext().getRealPath("/"));
        }
}

  • 配置web.xml
  <!--监听器-->
  <listener>
    <listener-class>taeyeon.com.servlet.StateApplicationListener</listener-class>
  </listener>
  
  • 输出
//容器启动时:
容器初始化----->D:\taeyeon\weblearn\src\main\webapp\
//容器关闭时:
容器销毁----->D:\taeyeon\weblearn\src\main\webapp\

我这里配置的虚拟路径是"/"。 2. 注意:所有的Servlet程序都必须在web.xml中进行配置,当然有的可以用注解来代替,如果在同一个web.xml中同时配置Servlet,过滤器,监听器的话,最好按照以下顺序:

  • 先配置过滤器
  • 配置监听器
  • 配置servlet
属性监听:ServletContextAttributeListener接口
  • 对此接口定义的方法如下
NO 方法 描述
1 public void attributeAdded(ServletContextAttributeEvent scab) 增加属性时触发
2 public void attributeREMOVED(ServletContextAttributeEvent scab) 删除属性时触发
3 public void attributeReplaced(ServletContextAttributeEvent scab) 修改替换属性时触发
  1. 在上下文监听中,一旦触发了ServletContextAttributeeListener接口中定义的事件后,可以通过ServletContextAttributeEvent进行事件的处理,此事件定义的方法如下:
NO 方法 描述
1 public String getName() 取得设置的属性名称
2 public Object getValue() 取得设置的属性内容
实例
package taeyeon.com.servlet;

import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/listener/application/attribute")
public class AttributerApplicationListener extends HttpServlet implements ServletContextAttributeListener {
        @Override
        public void attributeAdded(ServletContextAttributeEvent event) {
                String name = event.getName();
                Object value =  event.getValue();
                System.out.print("增加属性:");
                System.out.println(name+"----->"+value);
        }

        @Override
        public void attributeRemoved(ServletContextAttributeEvent event) {
                String name = event.getName();
                Object value = event.getValue();
                System.out.print("删除属性:");
                System.out.println(name+"----->"+value);
        }

        @Override
        public void attributeReplaced(ServletContextAttributeEvent event) {
                String name = event.getName();
                Object value =  event.getValue();
                System.out.print("替换属性:");
                System.out.println(name+"----->"+value);
        }

        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                req.getServletContext().setAttribute("name","Taeyeon");
                req.getServletContext().removeAttribute("name");
                req.getServletContext().setAttribute("name","Yoona");
        }
}

web.xml

  <listener>
    <listener-class>taeyeon.com.servlet.AttributerApplicationListener</listener-class>
  </listener>
  1. 启动服务器
增加属性:org.apache.jasper.compiler.TldLocationsCache----->org.apache.jasper.compiler.TldLocationsCache@244fd30e
增加属性:org.apache.jasper.runtime.JspApplicationContextImpl----->org.apache.jasper.runtime.JspApplicationContextImpl@14ef292

当启动服务器会初始化这两个对象,给他们设置属性值。大概是根据你工程里的引入jar包的问题而初始化这些属性。对测试无影响。

  • TldLocationsCache:(A container for all tag libraries that are defined "globally" for the webapplication.)Web应用程序“全局”定义的所有标记库的容器。
  • JspApplicationContextImpl
  1. 启动给服务Servlet输出,页面输入当前服务访问地址。
增加属性:name----->Taeyeon
替换属性:name----->Taeyeon
删除属性:name----->Yoona
  1. 在这里我们可以发现,执行第一次设置属性name时,会触发新增属性的方法,这时会输出‘增加属性:name----->Taeyeon’;然后运行到第二次设置name时,会触发替换属性的方法,应该是输出替换后的值,但是我们发现输出的是替换前的值‘替换属性:name----->Taeyeon’,也就是说在触发替换事件时使用getXXX获取的是被替换的值;运行到删除属性name时,会触发删除事件,输出‘删除属性:name----->Yoona’

对Session监听

  • 再监听器中,针对session的监听操作主要使用HttpSessionListener、HttpSessionAttributeListener和HttpSessionBindingListener接口。
session状态监听:HttpSessionListener
  1. 当需要对创建session和删除session的操作进行监听时,可以使用javax.servlet.http.HttpSessionListener接口,方法定义如下
NO 方法 描述
1 public void sessionCreated(HttpSessionEvent hse) 创建session时调用
2 public void sessionDestroyed(HttpSessionEvent hse) 销毁session时调用
  1. 当销毁session后,将产生HttpSessionEvent事件,此事件定义的方法如下:
NO 方法 描述
1 public HttpSession getSession() 取得当前session对象
实例
package taeyeon.com.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
@WebServlet("/listener/session/state")
public class StateSessionListener extends HttpServlet implements HttpSessionListener {
        @Override
        public void sessionCreated(HttpSessionEvent se) {
                System.out.println("创建session对象时ID------->"+se.getSession().getId());
        }

        @Override
        public void sessionDestroyed(HttpSessionEvent se) {
                System.out.println("销毁session对象时ID-------->"+se.getSession().getId());
        }

        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                HttpSession session=req.getSession();//创建session对象
                try {
                        Thread.sleep(5000);//单位为毫秒
                        session.invalidate();
                } catch (InterruptedException e) {
                        e.printStackTrace();
                }

        }
}

web.xml

 <listener>
    <listener-class>taeyeon.com.servlet.StateSessionListener</listener-class>
  </listener>
  1. 运行该servlet类输出:
创建session对象时ID------->57CA74DF0AE62779F1A20DF8077D51A7
销毁session对象时ID------->57CA74DF0AE62779F1A20DF8077D51A7
  1. 在设置让session销毁的方法除了调用 session.invalidate();方法外,还有设置当前session的最大生存时间调用 session.setMaxInactiveInterval(5)单位为秒;配置web.xml文件也可以实现:
  <session-config>
    <session-timeout>4</session-timeout><!--单位为分钟-->
  </session-config>

session默认时间为30分钟,是在用户没有对该session有任何操作开始算时间。

session属性监听:HttpSessionAttributeListener
  1. 要对session的属性操作进行监听,则需要实现javax.servlet.http.HttpSessionAttributeListener接口,此接口定义如下方法
NO 方法 描述
1 public void attributeAdded(HttpSessionBindingEvent se) 增加属性时触发
2 public void attributeREMOVED(HttpSessionBindingEvent se) 删除属性时触发
3 public void attributeReplaced(HttpSessionBindingEvent se) 修改替换属性时触发
  1. 当进行属性操作时,将根据对属性的操作触发HttpSessionAttributeListener接口中的方法,每个操作都会产生一个HttpSessionBindingEvent事件,此事件定义的方法如下:
NO 方法 描述
1 public String getName() 取得设置的属性名称
2 public Object getValue() 取得设置的属性内容
3 public HttpSession getSession() 返回当前session对象
实例
package taeyeon.com.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
@WebServlet("/listener/session/attribute")
public class AttributeSessionListener extends HttpServlet implements HttpSessionAttributeListener {
        @Override
        public void attributeAdded(HttpSessionBindingEvent event) {
                String name = event.getName();
                Object value = event.getValue();
                System.out.print("增加属性:");
                System.out.println(name + "----->" + value+"sessionID----->"+event.getSession().getId());
        }

        @Override
        public void attributeRemoved(HttpSessionBindingEvent event) {
                String name = event.getName();
                Object value = event.getValue();
                System.out.print("删除属性:");
                System.out.println(name + "----->" + value+"sessionID----->"+event.getSession().getId());
        }

        @Override
        public void attributeReplaced(HttpSessionBindingEvent event) {
                String name = event.getName();
                Object value = event.getValue();
                System.out.print("替换属性:");
                System.out.println(name + "----->" + value+"sessionID----->"+event.getSession().getId());
        }

        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                HttpSession session=req.getSession();//获取,如果没有则创建session对象
                session.setAttribute("name","Taeyeon");
                session.setAttribute("name","Yoona");
                session.removeAttribute("name");
        }
}

web.xml

  <listener>
    <listener-class>taeyeon.com.servlet.AttributeSessionListener</listener-class>
  </listener>
  1. 运行该servlet类输出:
增加属性:name----->Taeyeon------->sessionID----->0AA1C9FD0D67B81A568133CAC00DD64A
替换属性:name----->Taeyeon------->sessionID----->0AA1C9FD0D67B81A568133CAC00DD64A
删除属性:name----->Yoona------->sessionID----->0AA1C9FD0D67B81A568133CAC00DD64A
  1. 这里的输出性质一样,替换事件的触发是获取的被替换的属性。
session属性监听: HttpSessionBindingListener接口
  1. 之前讲的session监听器都需要在web.xml文件中配置才能起作用,但是Servlet也提供了一种不用配置也可直接使用的接口:HttpSessionBindingListener。该接口实现对对象绑定到session时触发的事件处理接口;常用方法如下:
NO 方法 描述
1 public void valueBound(HttpSessionBindingEvent sbe) 绑定对象到session时触发
2 public void valueUnBound(HttpSessionBindingEvent sbe) 从session中移除对象时触发
实例
package taeyeon.com.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

@WebServlet("/binding/session/listener")
public class BindingSessionListener extends HttpServlet implements HttpSessionBindingListener {
        private String name;
        private Integer age;
        public BindingSessionListener(){

        };
        public BindingSessionListener(String name, Integer age) {
                this.setName(name);
                this.setAge(age);
        }

        public String getName() {
                return name;
        }

        public void setName(String name) {
                this.name = name;
        }

        public Integer getAge() {
                return age;
        }

        public void setAge(Integer age) {
                this.age = age;
        }


        @Override
        public void valueBound(HttpSessionBindingEvent event) {
                System.out.println("绑定对象到session时----->" + this.getName() + ":" + this.getAge() + "---->" + event.getSession().getId() + "---->" + event.getSource());
        }

        @Override
        public void valueUnbound(HttpSessionBindingEvent event) {
                System.out.println("移除对象到session时----->" + this.getName() + ":" + this.getAge() + "---->" + event.getSession().getId() + "---->" + event.getSource());

        }

        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                BindingSessionListener use = new BindingSessionListener("Taeyeon", 18);
                req.getSession().setAttribute("name", use);
                req.getSession().removeAttribute("name");
                req.getSession().getClass();
                req.getSession().getClass();
        }
}
  1. 输出
绑定对象到session时----->Taeyeon:18---->E8D4F958D5C5EFE15C92CA8521B27F8D---->org.apache.catalina.session.StandardSessionFacade@28121878
移除对象到session时----->Taeyeon:18---->E8D4F958D5C5EFE15C92CA8521B27F8D---->org.apache.catalina.session.StandardSessionFacade@28121878
  1. 利用此方法可以保存用户的登陆名。

对request监听

  • 在servlet2.4之后增加了对request操作的监听,主要使用ServletRequestListener和ServletRequestAttributeListener两个接口。
请求状态监听:ServletRequestListener接口
  1. 当需要对用户的每次请求进行监听时,可以使用javax.servlet.ServletRequestListener接口,此接口定义如下方法
NO 方法 描述
1 public void requestInitialized(ServletRequestEvent sre) 开始请求时触发
2 public void requestDestroyed(ServletRequestEvent sre) 结束请求时触发
  1. ServletRequestListener接口一旦被触发,将产生ServletRequestEvent事件对象,此对象定义如下方法:
NO 方法 描述
1 public ServletRequest getServletRequest 获取request对象
2 public ServletContext getServletContext 获取ServletContext对象
实例
package taeyeon.com.servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class StateRequestListener  implements ServletRequestListener {

        @Override
        public void requestInitialized(ServletRequestEvent sre) {

                System.out.println("当产生请求时request:"+sre.getServletRequest().getRemoteAddr());//获取代理ip
                System.out.println("当产生请求时application:"+sre.getServletContext().getRealPath("/"));
        }
        @Override
        public void requestDestroyed(ServletRequestEvent sre) {
                System.out.println("当请求结束时request:"+sre.getServletRequest().getRemoteAddr());
                System.out.println("当请求结束时application:"+sre.getServletContext().getRealPath("/"));
        }
}

  1. 当客户端发送请求时,触发ServletRequestListener接口产生ServletRequestEvent事件,输出:
当请求结束时request:0:0:0:0:0:0:0:1
当请求结束时application:D:\taeyeon\weblearn\src\main\webapp\
当产生请求时request:0:0:0:0:0:0:0:1
当产生请求时application:D:\taeyeon\weblearn\src\main\webapp\
  1. 前面的监听都用的时配置web.xml,现在我们尝试利用注解来替换标签。
request属性监听:ServletRequestAttributeListener接口
  1. 对request范围属性的监听可以使用javax.servlet.ServletRRequestAttributeListener接口,此接口定义的方法如下:
NO 方法 描述
1 public void attributeAdded(ServletRequestAttributeEvent sral) request对象增加属性是触发
2 public void attributeRemoved(ServletRequestAttributeEvent sral) request对象移除属性是触发
3 public void attributeReplaced(ServletRequestAttributeEvent sral) request对象替换属性是触发
  1. 加入监听器之后,request属性的操作都会触发javax.servlet.ServletRRequestAttributeListener接口的ServletRequestAttributeEvent事件,此事件定义如下方法:
NO 方法 描述
1 public String getName() 获取设置的属性名
2 public Object getValue() 获取设置的属性值
实例
package taeyeon.com.servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/attribute/request/listener")
@WebListener
public class AttributeRequestListener extends HttpServlet implements ServletRequestAttributeListener {
        @Override
        public void attributeAdded(ServletRequestAttributeEvent srae) {
                System.out.println("request对象增加属性时------>" + srae.getName() + ":" + srae.getValue());
        }

        @Override
        public void attributeRemoved(ServletRequestAttributeEvent srae) {
                System.out.println("request对象删除属性时------>" + srae.getName() + ":" + srae.getValue());


        }

        @Override
        public void attributeReplaced(ServletRequestAttributeEvent srae) {
                System.out.println("request对象替换属性时------>" + srae.getName() + ":" + srae.getValue());
        }

        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                req.setAttribute("name", "Taeyeon");
                req.setAttribute("name", "Yoona");
                req.removeAttribute("name");
        }
}

  1. 输出
request对象替换属性时------>org.apache.catalina.ASYNC_SUPPORTED:true
request对象增加属性时------>name:Taeyeon
request对象替换属性时------>name:Taeyeon
request对象删除属性时------>name:Yoona
  • org.apache.catalina.ASYNC_SUPPORTED:true;设置请求支持异步处理,tomcat容器在每次请求时会自动增加属性org.apache.catalina.ASYNC_SUPPORTED,值为true会设置会可异步处理,false反之。
  • 替换属性还是get到的替换之前的数据。
总结:
  1. 从这三个域的事件监听中可以看出来所有的接口的XXXAttributeEvent事件都继承于XXXEvent。
  2. 所有的属性替换事件被触发时使用事件的方法getXXX到的数据都是修改之前的数据。
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!