1. 程式人生 > >java 學習之路 - web監聽器

java 學習之路 - web監聽器

Language 被調用 eat oncreate sys 路徑 director art content

什麽是web監聽器
web監聽器主要是對Servlet對象進行監聽和動作的,它可以監聽客戶端的請求,服務端的操作等

web監聽器的分類

根據監聽的域對象可以分為三類
    1.監聽Servlet上下文對象的監聽器
        1. 對Servlet上下文對象初始化及對象銷毀動作進行監聽的  ServletContextListener
        2. 對Servlet上下文對象的屬性進行監聽的 ServletContextAttributeListener
    2.監聽HTTP會話 Session對象的監聽器
        1. 對HTTP Session對象初始化及銷毀動作進行監聽的  HttpSessionListener
        2. 對HTTP Session對象的屬性進行監聽的  HttpSessionAttributeListener
        3. 對HTTP Session對象設置的屬性對象進行監聽的 HttpSessionBindingListener
        4. 對HTTP Session對象的活躍性進行監聽的 HttpSessionActivationListener
    3.監聽客戶端請求Servlet Request對象的監聽器
        1. 對Servlet Request對象初始化及銷毀動作進行監聽的 ServletRequestListener
        2. 對Servlet Request對象的屬性進行監聽的 ServletRequestAttributeListener

各監聽器的使用Demo

 註:本文使用的是Servlet3.0,所以基於@WebListener註解進行代碼演示,如果是其他版本只需在web.xml文件中配置listener即可
1. 監聽Servlet上下文對象的 ServletContextListener
    要對Servlet上下文 對象進行監聽只需實現ServletContextListener接口即可,此接口只有兩個方法,分別為Servlet啟動初始化方法contextInitialized(可以對ServletContext做相應的初始化操作),以及Servlet銷毀方法contextDestroyed(可以對ServletContext所持有的資源進行釋放);在tomcat中通start命令啟動時,監聽到Servlet對象的創建後contextInitialized方法會被執行,當執行shutdown命令時,監聽到Servlet對象將被銷毀,contextDestroyed方法會被執行。
@WebListener
public class MyServletContextListener implements ServletContextListener {
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("---------------------------------------------");
        System.out.println("MyServletContextListener contextInitialized");
        System.out.println("---------------------------------------------");
    }

    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("---------------------------------------------");
        System.out.println("MyServletContextListener contextDestroyed");
        System.out.println("---------------------------------------------");
    }
}

技術分享圖片

2.監聽Servlet上下文對象屬性變化的 ServletContextAttributeListener
要對Servlet上下文 對象的屬性變化進行監聽只需實現ServletContextAttributeListener接口即可,此接口只有三個方法,分別為屬性新增時的監聽方法(attributeAdded),通過ServletContextAttributeEvent 參數可以對ServletContext及新增的屬性內容進行操作;已有屬性內容被替換時的監聽方法(attributeReplaced),此方法在屬性被重復賦值(內容替換)時調用,可通過ServletContextAttributeEvent 參數進行操作;當ServletContext的屬性被移除時的監聽方法(attributeRemoved),通過ServletContextAttributeEvent 參數獲取ServletContext屬性內容時已是空。
@WebListener
public class MyServletContextAttributeListener implements ServletContextAttributeListener {
    public void attributeAdded(ServletContextAttributeEvent event) {
        System.out.print("MyServletContextAttributeListener attributeAdded : [value=");
        ServletContext servletContext = event.getServletContext();
        Enumeration<String> attributeNames = servletContext.getAttributeNames();
        while (attributeNames.hasMoreElements()) {
            System.out.print(attributeNames.nextElement() + ", ");
        }
        System.out.println("]");
        System.out.println("add ServletContextAttribute and value = " + servletContext.getAttribute("name"));

    }

    public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
        ServletContext servletContext = servletContextAttributeEvent.getServletContext();
        System.out.println("MyServletContextAttributeListener attributeRemoved and value = " + servletContext.getAttribute("name"));

    }

    public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
        ServletContext servletContext = servletContextAttributeEvent.getServletContext();
        System.out.println("MyServletContextAttributeListener attributeReplaced and value = " + servletContext.getAttribute("name"));
    }
}

JSP代碼:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello ServletContextAttributeListener!</h2>
<p>ServletContext changes</p>
<p>request.getServletContext() setAttribute</p>
<p><b>request.getServletContext().setAttribute("name", "add value");</b></p>
<%
    ServletContext servletContext = request.getServletContext();
    servletContext.setAttribute("name", "add value");
%>
<hr/>
<p>request.getServletContext() replaceAttribute</p>
<p><b>request.getServletContext().setAttribute("name", "replace value");</b></p>
<%
    servletContext.setAttribute("name", "replace value");
%>
<hr/>
<p>request.getServletContext() removeAttribute</p>
<p><b>request.getServletContext().removeAttribute("name");</b></p>
<%
    servletContext.removeAttribute("name");
%>
</body>
</html>

技術分享圖片

3. 對於HttpSession的創建,銷毀以及屬性的監聽與ServletContext類似,分別對應HttpSessionListener和HttpSessionAttributeListener,它們的接口方法與ServletContext接口方法也是類似,此處不再贅述,另外,對於HttpSession的操作可通過HttpSessionEvent和HttpSessionBindingEvent參數進行獲取,貼出代碼。
@WebListener
public class MyHttpSessionListener implements HttpSessionListener {
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        HttpSession session = httpSessionEvent.getSession();
        System.out.println("MyHttpSessionListener sessionCreated : " + session.getId());
    }

    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        HttpSession session = httpSessionEvent.getSession();
        System.out.println("MyHttpSessionListener sessionDestroyed : " + session.getId());
    }
}

@WebListener
public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener {
    public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
        HttpSession session = httpSessionBindingEvent.getSession();
        System.out.println("MyHttpSessionAttributeListener attributeAdded and id = " + session.getId() + ", value = " + session.getAttribute("name"));
    }

    public void attributeRemoved(HttpSessionBindingEvent event) {
        HttpSession session = event.getSession();
        System.out.println("MyHttpSessionAttributeListener attributeRemoved and id = " + session.getId() + ", value = " + event.getValue());
    }

    public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
        HttpSession session = httpSessionBindingEvent.getSession();
        System.out.println("MyHttpSessionAttributeListener attributeReplaced and id = " + session.getId() + ", value = " + session.getAttribute("name"));
    }
}

JSP代碼:
        註:HttpSessionListener的監聽在通過瀏覽器訪問服務時即可動作,所以此處沒有加操作代碼。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello HttpSessionAttributeListener</h2>
<p>HttpSessionAttribute changes</p>
<p>request.getSession() setAttribute</p>
<p><b>request.getSession().setAttribute("name", "add value");</b></p>
<%
    HttpSession httpSession = request.getSession();
    httpSession.setAttribute("name", "add value");
%>
<hr/>
<p>request.getSession() replaceAttribute</p>
<p><b>request.getSession().setAttribute("name", "replace value");</b></p>
<%
    httpSession.setAttribute("name", "replace value");
%>
<hr/>
<p>request.getSession() removeAttribute</p>
<p><b>request.getSession().removeAttribute("name");</b></p>
<%
    httpSession.removeAttribute("name");
%>
<hr/>
</body>
</html>

技術分享圖片

4. HttpSessionBindingListener用於監聽其實現類本身,當實現類對象被添加到session中時(session.setAttribute()),會調用valueBound方法,參數HttpSessionBindingEvent中包含session和實體信息,當實現類對象被從session中移除(session.removeAttribute())或者session失效時,會調用valueUnbound方法。另外,此listener的方法在HttpSessionAttributeListener方法之前執行。
public class MyHttpSessionBindingListener implements HttpSessionBindingListener {
    private String name;

    public MyHttpSessionBindingListener(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "MyHttpSessionBindingListener{" +
                "name=‘" + name + ‘\‘‘ +
                ‘}‘;
    }

    //被設置到session中(setAttribute)
    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        HttpSession session = event.getSession();
        System.out.println("HttpSessionBindingListener bean被設置到session中,sessionId=" + session.getId() + ", bean: " + event.getValue());
    }

    //從session中解除(removeAttribute)
    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        HttpSession session = event.getSession();
        System.out.println("HttpSessionBindingListener bean在session中被移除,sessionId=" + session.getId() + ", bean: " + event.getValue());
    }
}

JSP代碼:
<%@ page import="MyHttpSessionBindingListener" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello HttpSessionBindingListener</h2>
<p>HttpSessionBinding changes</p>
<p>session setAttribute</p>
<%
    Object name = session.getAttribute("name");
    if (name == null) {
        MyHttpSessionBindingListener bindingListener = new MyHttpSessionBindingListener("SessionBean");
        session.setAttribute("name", bindingListener);
%>
<p><b>session.setAttribute("name", "new MyHttpSessionBindingListener("SessionBean")");</b></p>
<%} else {%>
<p><b>session.getAttribute("name") : <%= name%>
</b></p>
<%}%>
<hr/>
<p>request.getSession() removeAttribute</p>
<p><b>request.getSession().removeAttribute("name");</b></p>
<%
    try {
        Thread.sleep(3000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    session.removeAttribute("name");
%>
<hr/>
</body>
</html>

技術分享圖片

5. Session的持久化操作:對於Tomcat服務器來說,可以通過配置context.xml文件來啟用此功能(Tomcat中默認沒有啟用此功能),在Session即將超時時生成sessionId.session文件,配置如下:
    註:當Session在系統中過期時,則Session信息會被清除,同時sessionId.session文件也會被刪除
            <Context>
                    <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
                            <Store className="org.apache.catalina.session.FileStore" directory="H:\selfwork\"></Store>
                    </Manager>
            </Context>
            * maxIdleSwap-session處於不活動狀態長時間(s),sesson對象轉移到FileStore中;(-1表示沒有限制)
            * directory - 存儲Session文件的路徑
            PersistentManager提供了把Session對象保存到Session store中的管理器,Tomcat目前提供了兩種Store的實現方式方式,分別為org.apache.Catalina.FileStore,將Session對象以本地文件的方式存儲在指定目錄中;org.apache.Catalina.JDBCStore,將Session對象存儲在指定的數據庫中,本文以文件的形式進行演示,並且本文對於PersistentManager 和 Session store 的配置,原理沒有做深入解析,只是做Session的持久化功能說明。
6. HttpSessionActivationListener同樣是用於監控實現類本身,當實現類對象bean被添加到session中(session.setAttribute())後,在session被序列化(鈍化)到文件時,sessionWillPassivate方法將被調用(只有保存到Session中的對象才會被監聽到),參數HttpSessionEvent含有Session的相關信息,由於現類對象bean會被進行序列化操作,所以實現類同時需要實現Serializable接口。
public class MyHttpSessionActivationListener implements HttpSessionActivationListener, Serializable {
    private String name;

    public MyHttpSessionActivationListener(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    public void sessionWillPassivate(HttpSessionEvent httpSessionEvent) {
        HttpSession session = httpSessionEvent.getSession();
        System.out.println("MyHttpSessionActivationListener sessionWillPassivate(session 即將超時,bean被序列化到本地) and sessionId = " + session.getId() + ", " + this.toString());
    }

    public void sessionDidActivate(HttpSessionEvent httpSessionEvent) {
        HttpSession session = httpSessionEvent.getSession();
        System.out.println("MyHttpSessionActivationListener sessionDidActivate(session 即將激活,bean被反序列化到內存) and sessionId = " + session.getId() + ", " + this.toString());
    }

    @Override
    public String toString() {
        return "MyHttpSessionActivationListener{" +
                "name=‘" + name + ‘\‘‘ +
                ‘}‘;
    }
}

JSP代碼:
<%@ page import="com.MyHttpSessionActivationListener" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello HttpSessionActivationListener</h2>
<p>HttpSessionActivation changes</p>
<%
    Object name = session.getAttribute("name");
    if (name == null) {
        MyHttpSessionActivationListener activationListener = new MyHttpSessionActivationListener("SessionActivationBean");
        session.setAttribute("name", activationListener);
%>
<p>session setAttribute</p>
<p><b>session.setAttribute("name", "activationListener");</b></p>
<%} else {%>
<p>session getAttribute</p>
<p>
    <b>session.getAttribute("name") : <%= name%>
    </b>
</p>
<%}%>
<hr/>
</body>
</html>

技術分享圖片
技術分享圖片

當內存中沒有session信息時,通過指定sessionId訪問服務器時(或者在原有頁面中重新刷新時),根據sessionId.session文件(反序列化)會重新載入序列化的Session信息,同時,sessionDidActivate方法被調用,參數HttpSessionEvent中含義反序列化的Session及對象bean信息

技術分享圖片

7. 監聽客戶端請求Servlet Request對象的監聽器與ServletContext監聽器同樣類似,分別對應ServletRequestListener 和 ServletRequestAttributeListener,它們的接口方法與ServletContext接口方法也是類似,此處不再贅述,另外,對於ServletRequest的操作可通過ServletRequestEvent和ServletRequestAttributeEvent參數進行獲取,貼出代碼。
 ServletRequestListener 監聽器
@WebListener
public class MyServletRequestListener implements ServletRequestListener {
    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
        ServletRequest servletRequest = servletRequestEvent.getServletRequest();
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String attribute = (String) request.getAttribute("name");
        System.out.println("MyServletRequestListener requestDestroyed and request attribute : " + attribute);
    }

    public void requestInitialized(ServletRequestEvent servletRequestEvent) {
        ServletRequest servletRequest = servletRequestEvent.getServletRequest();
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        request.setAttribute("name", "requestInitialized");
        System.out.println("MyServletRequestListener requestInitialized and request set attribute : [name = requestInitialized]");
    }
}

JSP代碼:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello ServletRequestListener!</h2>
<p>ServletRequestListener changes</p>
<p>request get init attribute</p>
<p><b>request.getAttribute("name");</b></p>
<%
    String name = (String) request.getAttribute("name");
%>
<p>request init value is : <%= name%>
</p>
<hr/>
<p>request.setAttribute</p>
<p><b>request.setAttribute("name", "add ServletRequestListener value");</b></p>
<%
    request.setAttribute("name", "add ServletRequestListener value");
%>
<hr/>
</body>
</html>

技術分享圖片

ServletRequestAttributeListener監聽器
@WebListener
public class MyServletRequestAttributeListener implements ServletRequestAttributeListener {
    public void attributeAdded(ServletRequestAttributeEvent event) {
        Object value = event.getValue();
        System.out.println("MyServletRequestAttributeListener attributeAdded and content is : " +
                event.getName() + " = " + value);
    }

    public void attributeRemoved(ServletRequestAttributeEvent event) {
        Object value = event.getValue();
        System.out.println("MyServletRequestAttributeListener attributeRemoved and content is : " +
                event.getName() + " = " + value);
    }

    public void attributeReplaced(ServletRequestAttributeEvent event) {
        Object value = event.getValue();
        System.out.println("MyServletRequestAttributeListener attributeReplaced and content is : " +
                event.getName() + " = " + value);
    }
}

JSP代碼:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello ServletRequestAttributeListener!</h2>
<p>ServletRequestAttributeListener changes</p>
<p>request get init attribute</p>
<p><b>request.getAttribute("name");</b></p>
<%
    String name = (String) request.getAttribute("name");
%>
<p>request init value is : <%= name%>
</p>
<hr/>
<p>request.setAttribute</p>
<p><b>request.setAttribute("name", "add ServletRequestListener value");</b></p>
<%
    request.setAttribute("name", "add ServletRequestListener value");
%>
<hr/>
<p>request replace attribute</p>
<p><b>request.setAttribute("name", "add ServletRequestListener replace value");</b></p>
<%
    request.setAttribute("name", "add ServletRequestListener replace value");
%>
<hr/>
<p>request remove attribute</p>
<p><b>request.removeAttribute("name");</b></p>
<%
    request.removeAttribute("name");
%>
<hr/>
</body>
</html>

技術分享圖片

總結

第一次以博客的形式記錄了自己學習web listener的經過,與之前的使用雲筆記相比,發現自己需要提升的不僅僅是對各種技術的學習和掌握,對於自己的表達能力更需要進行訓練和提升,雖然只是把listener的各個demo實例以及自己的理解記錄下來,還是進行修修補補的更改了很多次。萬事總有開頭,每一天的點滴進步,才能成就非凡的卓越。

java 學習之路 - web監聽器