Web容器管理Servlet/JSP相关的对象生命周期, 若对HttpSession对象/ServletContext对象在生成, 销毁或相关属性设置(或改变)发生的时机感兴趣, 则可以实现对应的监听器(Listener).
1. ServletContext事件 监听器
与ServletContext事件相关的监听器有:
- 生命周期监听器: ServletContextListener
- 属性改变监听器: ServletContextAttributeListener
(1) ServletContextListener
1> ServletContextListener概述:
ServletContexListener接口是继承于EventListener接口, 主要用于知道Web应用程序何时已经初始化或即将结束销毁. 其中实现了contextInitialized()方法和contextDestroyed()方法, 分别在应用程序初始化后或即将结束前调用这两个方法.ServletContextListener接口的实现代码如下:
public interface ServletContextListener extends EventListener{
public void contextInitialized(ServletContextEvent sce);
public void contextDestroyed(ServletContextEvent sce);
}
//ServletContextEvent中封装了ServletContext, 可以通过getServletContext()方法来获得
2> ServletContextListener的使用说明
例: 在应用程序初始化过程中, 应该准备好数据库链线对象, 读取应用程序设置等动作, 如放置头像的目录信息, 是整个应用程序中的Servlet应该共享的数据, 不应该直接写死在每一个Servlet中. 假设日后需要修改, 则需要在每一个Servlet中去修改. 所以可以将目录设置为ServletContext的属性, 因为ServletContext在Web应用程序存活期间都会存在. 具体实现的部分代码如下:
实现ServletCotextListener接口
//本段代码实现ServletContextListener接口, 并对初始化操作的方法进行重定义
@WebListener
//WebListener标注没有设置初始化参数的属性, 若需设置初始参数, 则应在web.xml中进行设置:
//<context-param>
//<param-name>AVATAR_DIR</param-name>
//<param-value>/avatars</param-value>
//</context-param>
public class ContextParameterReader implements ServletContextListener{
public void contextInitialized(ServletContextEvent sce){
ServletContext context = sce.getServletContext(); //取得ServletContext对象
String avatars = context.getInitParamer("AVATAR_DIR"); //取得初始参数
context.setAttribute("avatars", avatars); //设置ServletContext属性
}
public void contextDestroyed(ServletContextEvent sce){};
}
在具体的Servlet中应用该监听器
@WebServlet("/avatar.view")
//仅设置URL模式, 而不必要设置该Servlet的initParams(初始化参数)
public class Avatar extends HttpServlet{
private String AVATAR_DIR;
@Override
public void init() throws ServletException{
AVATAR_DIR = (String)getServletContext().getAttribute("AVATAR_DIR");
//这样就可以直接获取到整个Web应用程序中设置的ServletContext属性, 整个Web应用程序的所有Servlet都可以共享具有该属性的数据, 而不用在每个Servlet中先设置初始化参数再取得初始化参数
}
}
(2) ServletContextAttributeListner
1> ServletContextAttributeListner概述
ServletContextAttributeListner继承与EventListener接口, 是监听属性改变的监听器, 如果想要对象在被设置/移除/或替换ServletContext属性时可以收到通知以进行一些其他的操作, 可以实现该接口. 该接口主要实现了三个方法:atrributeAdded(), atrributeRemoved(), attributeReplace(), 当在ServletContext中添加属性/移除属性/替换属性时, 就会调用相应的方法. ServletContextAttributeListner接口的代码如下:
public interface ServletContextAttributeListner extends EventListener{
public void attributeAdded(ServletContextAttributeEvent scae);
public void attributeRemoved(ServletContextAttributeEvent scae);
public void attributeReplaced(ServletContextAttributeEvent scae);
}
2> ServletContextAttributeListner的使用说明
ServletContextAttributeListner的使用与ServletContextListener的使用大致相同, 在用法这里不过多赘述.
2. HttpSession事件 监听器
JSP&Servlet中使用HttpSession来进行会话管理, 所谓会话管理, 就是记得此次会话与之后会话的关系. 将会话期间需要共享的数据保存在HttpSession中成为属性.
(1) HttpSessionListener
1> HttpSessionListener概述
HttpSessionListener接口继承与EventListener接口, 是HttpSession的生命周期监听器. 如果想要在HttpSession对象创建或结束时, 做些相应操作, 则可以实现HttpSessionListener接口. 该接口主要有两个方法: sessionCreated()方法和sessionDestroyed()方法. HttpSessionListener接口的代码如下:
public interface HttpSessionListener extends EventListener{
public void sessionCreated(HttpSessionEvent se);
public void sessionDestroyed(HttpSessionEvent se);
//可以通过传入的HttpSessionEvent的getSession()取得HttpSession对象
}
2> HttpSessionListener的使用说明
例: 有些网站为了防止用户重复登录, 会在数据库中设立一个字段来代表用户是否已经登录, 而用户注销后, 就会重置该字段. 现在有一个问题, 假设用户并没有正确注销帐号, 而是直接关闭了浏览器, 那么该帐号应该如何被正确注销并在数据库中正确重置登录字段呢?
因为HttpSession有其存活期限, 当用户没有注销而关闭浏览器后, 一段时间后, 该登录令牌会自动失效, 所以可以实现HttpSessionListener接口, 在HttpSession失效前检测并重置登录字段.
实现HttpSessionListener接口代码如下:
@WebListener()
public class ResetLoginHelper implements HttpSessionListener{
@Override
public void sessionCreated(HttpSessionEvent se){}
@Override
public void sessionDestroyed(HttpSessionEvent se){
HttpSession session = se.getSession();
String user = session.getAttribute("login");
//修改数据库中登录字段为注销状态
}
}
(2) HttpSessionAttributeListener
1> HttpSessionAttributeListener概述
HttpSessionAttributeListener继承于EventListener接口, 是属性改变监听器, 当会话对象中加入/移除/替换属性时, 相对应的attributeAdded()/attributeRemoved()/attributeReplaced()方法就会被调用. HttpSessionAttributeListener接口的代码如下:
public interface HttpSessionAttributeListener extends EventListener{
public void attributeAdded(HttpSessionBindingEvent se);
public void attributeRemoved(HttpSessionBindingEvent se);
pubic void attributeReplaced(HttpSessionBindingEvent se);
//HttpSessionBindingEvent中的getName()方法可以获得属性的名称, getValue()方法可以获得属性的值.
}
(3) HttpSessionBindingListener
1> HttpSessionBindingListener概述
HttpSessionBindingListener继承于EventListener接口, 是对象属性监听器, 如果有个即将加入HttpSession的属性对象, 希望在设置给HttpSession成为属性或者从HttpSession中移除时, 可以收到HttpSession的通知, 则可以让该对象实现HttpSessionBindingListener接口. 该接口有两个方法:valueBound()和valueUnbound(), 分别在对象加入HttpSession或移除时被调用, 该接口的代码如下:
public interface HttpSessionBindingListener extends EventListener{
public valueBound(HttpSessionBindingEvent event);
public valueUnbound(HttpSessionBindingEvent event);
//可以通过HttpSessionBindingEvent对象的getSession()方法取得HttpSession对象.
}
2> HttpSessionBindingListener的使用说明
例: 假设在用户登录程序中, 当用户输入正确的用户名和密码时, 会创建User类的实例, 希望在成为User类的实例时被加入成为HttpSession属性时, 可以自动从数据库中加入所需要的用户的其他数据, 比如地址照片等, 所以可以让User类来实现HttpSessionBindingListener接口.
User类的实现代码如下:
public class User implements HttpSessionBindingListener{
private String name;
private String data;
public User(String name){
this.name = name;
}
public void valueBound(HttpSessionBindingEvent event){
this.data = name + "来自数据库的数据...";
}
public void valueUnbound(HttpSessionBindingEvent event){}
public String getData(){
return data;
}
public String getName(){
return name;
}
}
在Servlet中应用实现了HttpSessionBindingListener接口的User类的代码如下:
@WebServlet("/login.do")
public class Login extends HttpServlet{
...
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
...
String page = "form.html";
//containsKey(name):判断是否存在此键名
if(users.containsKey(name) && users.get(name).equals(passwd)){
User user = new User(name); request.getSession().setAttribute("user", user);
page = "welcome.view";
}
response.sendRedirect(page);
}
}
(4) HttpSessionActivationListener
1> HttpSessionActivationListener概述
HttpSessionActivationListener是对象迁移监听器, 一般不会用到该监听器, 只有在使用到分布式环境时, 应用程序的对象可能分散在多个JVM中.
3. HttpServletRequest事件 监听器
(1) ServletRequestListener
1> ServletRequestListener概述
ServletRequestListener是请求对象的生命周期监听器, 继承于EventListener接口, 其中定义了两个方法:requestInitialized()和requestDestroyed()方法, 分别在请求初始化或结束之前被调用. ServletRequestListener接口的代码如下:
public interface ServletRequestListener extends EventListener{
public void requestInitialized(ServletRequestEvent sre);
public void requestDestroyed(ServletRequestEvent sre);
//可以通过传入的ServletRequestEvet对象的getRequest()方法来取得ServletRequest对象.
}
2> ServletRequestListener的使用说明
例: 假设有一个Servlet希望子请求创建或销毁时做一些动作, 则可以实现ServletRequestListener接口, 其代码如下:
public class SomeRequest implements ServletRequestListener{
...
}
(1) ServletRequestAttributeListener
1> ServletRequestAttributeListener概述
ServletRequestAttributeListener是请求对象的属性改变监听器, 其继承于EventListener接口, 主要有三个方法:attributeAdded()/attributeRemoved()/attributeReplace(), 分别在属性添加/移除/替换时被调用. ServletRequestAttributeListener接口的代码如下:
public interface ServletRequestAttributeListener extends EventListener{
public void attributeAdded(ServletRequestAttributeEvent sre);
public void attributeRemoved(ServletRequestAttributeEvent sre);
public void attributeReplace(ServletRequestAttributeEvent sre);
//ServletRequestAttributeEvent有getName()方法来取得属性指定的名称, getValue()方法来取得属性的值.值
}
- 生命周期监听器与属性改变监听器都必须使用@WebListener标注, 或在web.xml中进行设置, 这样容器才会知道要加载读取监听器相关设置.