之前總結的第一類 Listener,監聽的是 ServletContext、HttpSession和ServletRequest 這三個對象的創建和銷燬,接下來要介紹的第二類 Listener分別是ServletRequestAttributeListener、ServletContextAttributeListener和HttpSessionAttributeListener。
從名字不難看出,他們是監聽各自對象中屬性的Listener,每當對象的屬性發生變化(增加、修改或者刪除),相應的監聽器將會收到通知。XXXXXXAttributeListener 中方法的名稱相同,以HttpSessionAttributeListener接口爲例:
package javax.servlet.http;
import java.util.EventListener;
import javax.servlet.http.HttpSessionBindingEvent;
public interface HttpSessionAttributeListener extends EventListener {
default void attributeAdded(HttpSessionBindingEvent se) {
}
default void attributeRemoved(HttpSessionBindingEvent se) {
}
default void attributeReplaced(HttpSessionBindingEvent se) {
}
}
attributeAdded()
、attributeRemoved()
、attributeReplaced
分別在 Session 中的屬性被添加、移除和改變時被調用,從參數HttpSessionBindingEvent中可以獲得 Session 的詳細信息:
public String login(){
HttpSession session = ServletActionContext.getRequest().getSession();
session.setAttribute("UserName", username);
session.setAttribute("UserName", "defaultUserName");
session.removeAttribute("UserName");
return SUCCESS;
}
//自定義MyHttpSessionAttributeListener
public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener {
private Logger logger = Logger.getLogger(MyHttpSessionAttributeListener.class);
public void attributeAdded(HttpSessionBindingEvent se) {
logger.debug("attributeAdded: Name: "+ se.getName()+"; Value: "+ se.getValue());
}
public void attributeRemoved(HttpSessionBindingEvent se) {
logger.debug("attributeRemoved: Name: "+ se.getName()+"; Value: "+ se.getValue());
}
public void attributeReplaced(HttpSessionBindingEvent se) {
logger.debug("attributeReplaced: Name: "+ se.getName()+"; Value: "+ se.getValue());
}
}
在模擬登陸的函數中對 Session 進行一系列操作,可以看到控制檯輸出信息:
與 HttpSessionAttributeListener 的作用類似,ServletContextAttributeListener和ServletContextAttributeListener接口都提供了以上三個方法,用法也大致相同,下面直接給出實現了ServletContextAttributeListener和ServletContextAttributeListener接口的兩個自定義 Listener 類。
MyServletContextAttributeListener.java:
//...
public class MyServletContextAttributeListener implements ServletContextAttributeListener {
private Logger logger = Logger.getLogger(MyServletContextAttributeListener.class);
public void attributeReplaced(ServletContextAttributeEvent scae) {
logger.debug("attributeReplaced: Name: "+ scae.getName()+"; Value: "+ scae.getValue());
}
public void attributeRemoved(ServletContextAttributeEvent scae) {
logger.debug("attributeRemoved: Name: "+ scae.getName()+"; Value: "+ scae.getValue());
}
public void attributeAdded(ServletContextAttributeEvent scae) {
logger.debug("attributeAdded: Name: "+ scae.getName()+"; Value: "+ scae.getValue());
}
}
MyServletRequestAttributeListener.java:
public class MyServletRequestAttributeListener implements ServletContextAttributeListener {
private Logger logger = Logger.getLogger(MyServletRequestAttributeListener.class);
public void attributeReplaced(ServletContextAttributeEvent scae) {
logger.debug("attributeReplaced: Name: "+ scae.getName()+"; Value: "+ scae.getValue());
}
public void attributeRemoved(ServletContextAttributeEvent scae) {
logger.debug("attributeRemoved: Name: "+ scae.getName()+"; Value: "+ scae.getValue());
}
public void attributeAdded(ServletContextAttributeEvent scae) {
logger.debug("attributeAdded: Name: "+ scae.getName()+"; Value: "+ scae.getValue());
}
}
將之前login
函數中的代碼進行修改,使其操作 ServletContext 、Request 和 Session 中的 Attribute,再看控制檯的輸出:
函數 login():
public String login(){
ServletContext servletContext = ServletActionContext.getServletContext();
HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = request.getSession();
session.setAttribute("UserName", username);
session.setAttribute("UserName", "defaultUserName");
session.removeAttribute("UserName");
servletContext.setAttribute("UserName", username);
servletContext.setAttribute("UserName", "defaultUserName");
servletContext.removeAttribute("UserName");
request.setAttribute("UserName", username);
request.setAttribute("UserName", "defaultUserName");
request.removeAttribute("UserName");
return SUCCESS;
}
進行一次 Request 請求時控制檯的輸出:
由於在調用 login()
方法之前頁面已經進行過一次訪問,第二次訪問時並沒有創建或銷燬 Session,所以這裏只有 RequestListener 進行了響應。
基於上一篇文章的監聽對象創建和銷燬的 Listener,再加上監聽對象屬性的 Listener,實際使用中可以將自定義 Listener 同時繼承兩種接口,將對象的監聽事件放於一處,提高代碼的可維護性:
以 HttpSession 對象的監聽爲例:
//...
public class MyHttpSessionListener implements HttpSessionListener, HttpSessionAttributeListener{
private static Logger logger = Logger.getLogger(MyHttpSessionListener.class);
public void sessionCreated(HttpSessionEvent se) {
logger.debug("sessionCreated");
logger.debug(se.getSession().getId());
}
public void sessionDestroyed(HttpSessionEvent se) {
logger.debug("sessionDestroyed");
}
public void attributeReplaced(HttpSessionBindingEvent se) {
}
public void attributeRemoved(HttpSessionBindingEvent se) {
}
public void attributeAdded(HttpSessionBindingEvent se) {
}
}