2016年3月21日 星期一

Listener (Servlet 七)

※HttpSessionBindingListener

Servlet的內鍵觸發程式,也就是做了什麼事後,會自動做某件事
可以想成javascript的onXXX,譬如onClick,當使用者按一下滑鼠後,會自動做某件事
這裡的Binding是挷setAttribute(還要呼叫建構子)和removeAttribute


public class TestListener implements HttpSessionBindingListener {
    PrintWriter out;
    
    public TestListener(PrintWriter out){
        this.out = out;
    }
    
    @Override
    public void valueBound(HttpSessionBindingEvent e) {
        out.println("valueBound");
        out.println(e.getName());
        out.println(e.getValue());
    }
    
    @Override
    public void valueUnbound(HttpSessionBindingEvent e) {
        out.println("valueUnbound");
        out.println(e.getName());
        out.println(e.getValue());
    }
}

※寫一支class,實作HttpSessionBindingListener讓session觸發



resp.setContentType("text/plain");
req.getSession().setAttribute("out", new TestListener(resp.getWriter()));

※在doXXX加入這兩行就會觸發

※第一行不打也可以,只是不會換行,會變成空格,所以不寫的話也可以改成在listener那一支加<br />

※觸發的是valueBound,如果想觸發valueUnbound,就按一下重整或上一頁再下一頁,就會看到了,所以valueUnbound在reload、重整、呼叫removeAttribute、contain的預設30分session失效都會觸發



※ServletContextListener

container啟動和關閉時會觸發的listener


@WebListener
@WebInitParam(name = "p1", value = "ppp")
public class TestListener implements ServletContextListener {
// PrintWriter out;
//
// public TestListener(PrintWriter out) {
// this.out = out;
// }
    
    @Override
    public void contextInitialized(ServletContextEvent e) {
        System.out.println("contextInitialized");
        ServletContext sc = e.getServletContext();
        System.out.println(sc.getContextPath());
        System.out.println(sc.getInitParameter("p1"));
        System.out.println(sc.getInitParameter("abc"));
        System.out.println(sc.getInitParameter("def"));
    }
    
    @Override
    public void contextDestroyed(ServletContextEvent e) {
        System.out.println("contextDestroyed");
    }
}

※如果將out註解打開,程式無法啟動,會出現兩個錯誤
InstantiationException: listener.TestListener
NoSuchMethodException: listener.TestListener.<init>()
程式才剛啟動,當然是抓不到了

※這是annotation寫法,@WebListener有一個參數,是描述,很少人在寫

※@WebInitParam沒有作用,要設定初始參數只能寫在web.xml了



<listener>
    <listener-class>listener.TestListener</listener-class>
</listener>
    
<context-param>
    <param-name>abc</param-name>
    <param-value>111</param-value>
</context-param>
    
<context-param>
    <param-name>def</param-name>
    <param-value>222</param-value>
</context-param>

※listener包住listener-class,等同@WebListener,擇一使用

※在reload和關閉container時,會觸發contextDestroyed方法,注意和之前一樣,要按Servers的紅鈕,按Console的紅鈕和按右上角的X是不會執行到contextDestroyed方法的



※ServletContextAttributeListener

ServletContext在新增、取代、移除屬性時觸發


@WebListener
public class TestListener implements ServletContextAttributeListener {
    @Override
    public void attributeAdded(ServletContextAttributeEvent e) {
        System.out.println("attributeAdded");
        System.out.println(e.getName());
        System.out.println(e.getValue());
        System.out.println(e.getServletContext());
    }
    
    @Override
    public void attributeRemoved(ServletContextAttributeEvent e) {
        System.out.println("attributeRemoved");
        System.out.println(e.getName());
        System.out.println(e.getValue());
        System.out.println(e.getServletContext());
    }
    
    @Override
    public void attributeReplaced(ServletContextAttributeEvent e) {
        System.out.println("attributeReplaced");
        System.out.println(e.getName());
        System.out.println(e.getValue());
        System.out.println(e.getServletContext());
    }
}

※比較奇怪的是,我一run到jsp頁面,就會觸發added了,如下訊息:
attributeAdded
org.apache.jasper.runtime.JspApplicationContextImpl
org.apache.jasper.runtime.JspApplicationContextImpl@6f1943a6
org.apache.catalina.core.ApplicationContextFacade@4373821f


※測試

resp.setContentType("text/plain");
ServletContext sc = req.getServletContext();
sc.setAttribute("k", "v");
sc.setAttribute("k", "v");
sc.removeAttribute("k");

※取代時,就算value一樣也能觸發;移除時,一定要有key被移除才會觸發



※HttpSessionAttributeListener

HttpSession在新增、取代、移除屬性時觸發


@WebListener
public class TestListener implements HttpSessionAttributeListener {
    @Override
    public void attributeAdded(HttpSessionBindingEvent e) {
        System.out.println("attributeAdded");
        System.out.println(e.getName());
        System.out.println(e.getValue());
        System.out.println(e.getSession().getId());
    }
    
    @Override
    public void attributeRemoved(HttpSessionBindingEvent e) {
        System.out.println("attributeRemoved");
        System.out.println(e.getName());
        System.out.println(e.getValue());
        System.out.println(e.getSession().getId());
    }
    
    @Override
    public void attributeReplaced(HttpSessionBindingEvent e) {
        System.out.println("attributeReplaced");
        System.out.println(e.getName());
        System.out.println(e.getValue());
        System.out.println(e.getSession().getId());
    }
}

※因為是HttpSession,所以沒有getServletContext方法了



※測試

resp.setContentType("text/plain");
HttpSession session = req.getSession();
session.setAttribute("k", "v");
session.setAttribute("k", "v");
session.removeAttribute("x");

※和ServletContextAttributeListener一樣,但執行頁面時不會觸發



※HttpSessionListener


@WebListener
public class TestListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent e) {
        System.out.println("sessionCreated");
        System.out.println(e.getSession().getId());
    }
    
    @Override
    public void sessionDestroyed(HttpSessionEvent e) {
        System.out.println("sessionDestroyed");
        System.out.println(e.getSession().getId());
    }
}



※測試
HttpSession session = req.getSession();
session.invalidate();



HttpSessionActivationListener參考良葛格的網站,總之就是JVM搬到另一個JVM的觸發程式



※ServletRequestListener、ServletRequestAttributeListener

@WebListener
public class TestListener implements ServletRequestListener, ServletRequestAttributeListener {
    @Override
    public void requestDestroyed(ServletRequestEvent e) {
        System.out.println("requestDestroyed");
        System.out.println(e.getServletContext().getServletContextName());
        System.out.println(e.getServletRequest().getLocalName());
    }
    
    @Override
    public void requestInitialized(ServletRequestEvent e) {
        System.out.println("requestInitialized");
        System.out.println(e.getServletContext().getServletContextName());
        System.out.println(e.getServletRequest().getLocalName());
    }
    
    @Override
    public void attributeAdded(ServletRequestAttributeEvent e) {
        System.out.println("attributeAdded");
        System.out.println(e.getName());
        System.out.println(e.getValue());
    }
    
    @Override
    public void attributeRemoved(ServletRequestAttributeEvent e) {
        System.out.println("attributeRemoved");
        System.out.println(e.getName());
        System.out.println(e.getValue());
    }
    
    @Override
    public void attributeReplaced(ServletRequestAttributeEvent e) {
        System.out.println("attributeReplaced");
        System.out.println(e.getName());
        System.out.println(e.getValue());
    }
}



※測試

resp.setContentType("text/plain");
req.setAttribute("k", "v");
req.setAttribute("k", "v");
req.removeAttribute("k");

※和之前的大同小異

沒有留言:

張貼留言