Servlet监听器
一、简介
- 监听器的主要功能是负责监听web的各种操作,和js中的事件监听性质一样,当相关事件触发后将产生事件,并对此事件进行处理,在web中可以对对象application(servletContext)、session、request操作进行监听处理。
二、对application对象监听
- 对application监听,实际上就是对ServletContext监听,主要使用ServletContextListener和ServletContextAttributeeListener两个接口。
application状态监听:ServletContextListener接口
- 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("/"));
}
}
<!--监听器-->
<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,过滤器,监听器的话,最好按照以下顺序:
属性监听:ServletContextAttributeListener接口
NO |
方法 |
描述 |
---|
1 |
public void attributeAdded(ServletContextAttributeEvent scab) |
增加属性时触发 |
2 |
public void attributeREMOVED(ServletContextAttributeEvent scab) |
删除属性时触发 |
3 |
public void attributeReplaced(ServletContextAttributeEvent scab) |
修改替换属性时触发 |
- 在上下文监听中,一旦触发了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>
- 启动服务器
增加属性: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
- 启动给服务Servlet输出,页面输入当前服务访问地址。
增加属性:name----->Taeyeon
替换属性:name----->Taeyeon
删除属性:name----->Yoona
- 在这里我们可以发现,执行第一次设置属性name时,会触发新增属性的方法,这时会输出
‘增加属性:name----->Taeyeon’
;然后运行到第二次设置name时,会触发替换属性的方法,应该是输出替换后的值,但是我们发现输出的是替换前的值‘替换属性:name----->Taeyeon’
,也就是说在触发替换事件时使用getXXX获取的是被替换的值;运行到删除属性name时,会触发删除事件,输出‘删除属性:name----->Yoona’
。
对Session监听
- 再监听器中,针对session的监听操作主要使用HttpSessionListener、HttpSessionAttributeListener和HttpSessionBindingListener接口。
session状态监听:HttpSessionListener
- 当需要对创建session和删除session的操作进行监听时,可以使用javax.servlet.http.HttpSessionListener接口,方法定义如下
NO |
方法 |
描述 |
---|
1 |
public void sessionCreated(HttpSessionEvent hse) |
创建session时调用 |
2 |
public void sessionDestroyed(HttpSessionEvent hse) |
销毁session时调用 |
- 当销毁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>
- 运行该servlet类输出:
创建session对象时ID------->57CA74DF0AE62779F1A20DF8077D51A7
销毁session对象时ID------->57CA74DF0AE62779F1A20DF8077D51A7
- 在设置让session销毁的方法除了调用
session.invalidate();
方法外,还有设置当前session的最大生存时间调用 session.setMaxInactiveInterval(5)
单位为秒;配置web.xml文件也可以实现:
<session-config>
<session-timeout>4</session-timeout><!--单位为分钟-->
</session-config>
session默认时间为30分钟,是在用户没有对该session有任何操作开始算时间。
session属性监听:HttpSessionAttributeListener
- 要对session的属性操作进行监听,则需要实现javax.servlet.http.HttpSessionAttributeListener接口,此接口定义如下方法
NO |
方法 |
描述 |
---|
1 |
public void attributeAdded(HttpSessionBindingEvent se) |
增加属性时触发 |
2 |
public void attributeREMOVED(HttpSessionBindingEvent se) |
删除属性时触发 |
3 |
public void attributeReplaced(HttpSessionBindingEvent se) |
修改替换属性时触发 |
- 当进行属性操作时,将根据对属性的操作触发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>
- 运行该servlet类输出:
增加属性:name----->Taeyeon------->sessionID----->0AA1C9FD0D67B81A568133CAC00DD64A
替换属性:name----->Taeyeon------->sessionID----->0AA1C9FD0D67B81A568133CAC00DD64A
删除属性:name----->Yoona------->sessionID----->0AA1C9FD0D67B81A568133CAC00DD64A
- 这里的输出性质一样,替换事件的触发是获取的被替换的属性。
session属性监听: HttpSessionBindingListener接口
- 之前讲的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();
}
}
- 输出
绑定对象到session时----->Taeyeon:18---->E8D4F958D5C5EFE15C92CA8521B27F8D---->org.apache.catalina.session.StandardSessionFacade@28121878
移除对象到session时----->Taeyeon:18---->E8D4F958D5C5EFE15C92CA8521B27F8D---->org.apache.catalina.session.StandardSessionFacade@28121878
- 利用此方法可以保存用户的登陆名。
对request监听
- 在servlet2.4之后增加了对request操作的监听,主要使用ServletRequestListener和ServletRequestAttributeListener两个接口。
请求状态监听:ServletRequestListener接口
- 当需要对用户的每次请求进行监听时,可以使用javax.servlet.ServletRequestListener接口,此接口定义如下方法
NO |
方法 |
描述 |
---|
1 |
public void requestInitialized(ServletRequestEvent sre) |
开始请求时触发 |
2 |
public void requestDestroyed(ServletRequestEvent sre) |
结束请求时触发 |
- 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("/"));
}
}
- 当客户端发送请求时,触发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\
- 前面的监听都用的时配置web.xml,现在我们尝试利用注解来替换标签。
request属性监听:ServletRequestAttributeListener接口
- 对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对象替换属性是触发 |
- 加入监听器之后,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");
}
}
- 输出
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到的替换之前的数据。
总结:
- 从这三个域的事件监听中可以看出来所有的接口的XXXAttributeEvent事件都继承于XXXEvent。
- 所有的属性替换事件被触发时使用事件的方法getXXX到的数据都是修改之前的数据。
来源:oschina
链接:https://my.oschina.net/u/4045839/blog/3135387