監聽request session servletContext的建立與銷燬
監聽器:
* Java Web的三大元件:Servlet、Listener、Filter.* 注意:
* listener的觸發或呼叫,是不需要我們關注的.(Tomcat伺服器)
* Tomcat與JavaEE的版本是有對應的.
* Tomcat 7.0版本 - Servlet 3.0
* Tomcat 6.0版本 - Servlet 2.5
* 開發原則:不要追新.
* Listener對於我們來講:如何編寫.
* 八大監聽器:
* 第一組:用於監聽Servlet三個域物件的建立與銷燬* ServletRequestListner
* HttpSessionListener
* ServletContextListener
* 作用:用於監聽Servlet三個域物件的建立與銷燬.
* 三個域物件的建立與銷燬:
* Request物件:
* 建立:發生請求時.
* 銷燬:請求完成時.
* Session物件:
* 建立:發生請求時,並且執行getSession()語句.
* 銷燬:執行Session的銷燬方法invalidate().
* ServletContext物件:
* 建立:Tomcat啟動時.
* 銷燬:Tomcat關閉時.
因為是屬於servlet ,所以要在web.xml中進行配置:package app.java.listener1; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestListener; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; /** * 用於測試HttpSessionListener監聽器. * * 實現HttpSessionListener介面. * * 重寫該介面提供的所有方法. * @author JYL */ public class HttpSessionListenerTest implements HttpSessionListener,ServletRequestListener,ServletContextListener { /** * sessionCreated(HttpSessionEvent arg0) * * 該方法用於監聽Session物件的建立. * * 問題:應該是在Session物件建立之前還是之後被呼叫?後. * * 作用:可以實現必要的初始化工作. */ public void sessionCreated(HttpSessionEvent arg0) { System.out.println("我的Session物件終於被建立啦。。。"); /* * HttpSessionEvent事件物件: * * 獲取對應的Request物件. * * 獲取對應的ServletContext物件. */ } /** * sessionDestroyed(HttpSessionEvent arg0) * * 該方法用於監聽Session物件的銷燬. * * 問題:應該是在Session物件銷燬之前還是之後被呼叫?前. * * 作用:可以實現必要的資源釋放工作. */ public void sessionDestroyed(HttpSessionEvent arg0) { System.out.println("我的Session物件離我而去啦。。。"); } public void contextDestroyed(ServletContextEvent arg0) { } public void contextInitialized(ServletContextEvent arg0) { } public void requestDestroyed(ServletRequestEvent arg0) { } public void requestInitialized(ServletRequestEvent arg0) { } }
<!-- 在web.xml檔案中如何配置Listener -->
<!--
<listener>
<listener-class>app.java.listener1.HttpSessionListenerTest</listener-class>
</listener>
<listener>
<listener-class>app.java.listener2.ServletRequestAttributeListenerTest</listener-class>
</listener>
-->
<listener>
<listener-class>app.java.listener.demo.MyServletContextListener</listener-class>
</listener>
<listener>
<listener-class>app.java.listener.demo.MyHttpSessionListener</listener-class>
</listener>
jsp頁面:
<%
HttpSession mysession = request.getSession();
mysession.invalidate();
%>
* 第二組:用於監聽Servlet三個域物件的屬性變化(設定、刪除、修改)
* ServletRequestAttributeListener
* HttpSessionAttributeListener
* ServletContextAttributeListener
package app.java.listener2;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
/**
* 用於測試ServletRequestAttributeListener監聽器.
* @author JYL
*
*/
public class ServletRequestAttributeListenerTest implements ServletRequestAttributeListener {
/**
* attributeAdded()
* * 該方法用於監聽Request物件新增屬性.
*/
public void attributeAdded(ServletRequestAttributeEvent arg0) {
System.out.println("Request物件添加了一個屬性。。。");
}
/**
* attributeRemoved()
* * 該方法用於監聽Request物件刪除屬性.
*/
public void attributeRemoved(ServletRequestAttributeEvent arg0) {
System.out.println("Request物件刪除了一個屬性。。。");
}
/**
* attributeReplaced()
* * 該方法用於監聽Request物件修改屬性.
*/
public void attributeReplaced(ServletRequestAttributeEvent arg0) {
System.out.println("Request物件修改了一個屬性。。。");
}
}
jsp頁面:
<%
request.setAttribute("yttlj", "zhouzhiruo");
request.removeAttribute("yttlj");
%>
* 如何自定義監聽器:
* 第一步:* 建立Java類,實現上述八個監聽器介面之一.
* 重寫該介面提供的所有方法.
* 第二步:
* 在web.xml檔案中配置Listener.
<listener>
<listener-class>自定義Listener的完整路徑</listener-class>
</listener>
* 第三組:用於通知被繫結到Session物件的屬性.
* HttpSessionBindingListener
* 注意:
* 該監聽器應該由JavaBean類實現.(可以將JavaBean繫結到Session上) 繫結什麼java物件都可以
* 誰被繫結到Session上,誰就實現該監聽器.
* 該監聽器的作用:通知被繫結到Session的JavaBean物件.
* 使用該監聽器時,不需要在web.xml檔案中進行配置的.
JavaBean:
package app.java.listener3;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
/**
* 定義一個User的JavaBean.
* * 將該JavaBean物件繫結到Session中.
* * 該JavaBean實現HttpSessionBindingListener.
*
* 問題:
* * 當JavaBean實現了HttpSessionBindingListener介面.
* * 汙染了當前JavaBean.
* * 由監聽器提供了多餘的方法,不屬於JavaBean.
* * JavaBean說白了就是Java類,與JavaEE是無關的.
* * 一旦實現HttpSessionBindingListener介面,就與JavaEE是有關的.
*
* 最終建議:不建議使用.
* @author JYL
*/
public class User implements HttpSessionBindingListener {
private int id;
private String name;
private String job;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
/**
* valueBound(HttpSessionBindingEvent arg0)
* * 該方法用於監聽當前JavaBean被繫結到Session中.
* * 執行session.setAttribute()方法時,就是繫結.
*/
public void valueBound(HttpSessionBindingEvent arg0) {
System.out.println("這個JavaBean被成功地包養了。。。");
}
/**
* valueUnbound(HttpSessionBindingEvent arg0)
* * 該方法用於監聽當前JavaBean從Session中解綁.
* * 執行session.removeAttribute()方法時,就是解綁.
*/
public void valueUnbound(HttpSessionBindingEvent arg0) {
System.out.println("這個JavaBean被無情地拋棄啦。。。");
}
}
BeanServlet.java:
package app.java.listener3;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class BeanServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1 例項化JavaBean
User user = new User();
user.setId(1);
user.setName("zhangwuji");
user.setJob("jiaozhu");
HttpSession session = request.getSession();
//2 將該JavaBean的例項,繫結到Session物件中
session.setAttribute("user", user);
//3 從Session物件中刪除JavaBean物件
session.removeAttribute("user");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
* 第四組:用於監聽Session的鈍化與活化
* HttpSessionActivationListener
* Session的序列化* 當Tomcat伺服器正常關閉後,Session會自動被儲存到本地硬碟中.
* 在Tomcat伺服器的安裝目錄:%Catalina_HOME%\work\Catalina\localhost\Web工程名目錄中.
* 當Tomcat伺服器正常啟動後,Session會自動從本地硬碟中讀取到記憶體中.
* 儲存在本地硬碟中的序列化檔案,自動銷燬.
* 問題:
* Tomcat伺服器為什麼提供這麼一個機制?
建立一個Servlet用於向Session中存放資料內容。
package app.java.listener4;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class SessionServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
User user = new User();
user.setId(1);
user.setName("zhangwuji");
user.setJob("jiaozhu");
//1 獲取或建立Session物件
HttpSession session = request.getSession();
//2 向Session物件設定屬性內容
session.setAttribute("user", user);
//3 將session中的內容響應到頁面中
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("成功地向Session放置了內容.");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
建立一個Servlet用於從Session中讀取存放的資料內容。
package app.java.listener4;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class GetSessionServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
User user = (User)session.getAttribute("user");
System.out.println(user);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
在bean中監聽:
package app.java.listener4;
import java.io.Serializable;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
/**
* 定義一個User的JavaBean.
*
* @author JYL
*/
public class User implements HttpSessionActivationListener,Serializable {
private int id;
private String name;
private String job;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", job=" + job + "]";
}
public void sessionDidActivate(HttpSessionEvent arg0) {
System.out.println("Session成功地從火星迴來啦。。。");
}
public void sessionWillPassivate(HttpSessionEvent arg0) {
System.out.println("Session成功地逃離地球啦。。。");
}
}
* Session的鈍化與活化 * 實現步驟:
* 1編寫Servlet設定Session.
*2 在Tomcat安裝目錄%Catalina_HOME%\conf\Catalina\localhost目錄中,建立一個名為Web工程名的xml檔案.
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<!-- maxIdleSwap:指定多長時間後Session會被鈍化.(單位為分鐘) -->
<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1" >
<!--
directory:指定鈍化檔案的儲存目錄.
鈍化檔案儲存路徑:${CATALINA_HOME}\work\Catalina\localhost\Web工程名\${sessionid}.session
-->
<Store className="org.apache.catalina.session.FileStore" directory="mysession" />
</Manager>
</Context>
* 3建立JavaBean,用於繫結到Session中.
* 該JavaBean實現了HttpSessionActivationListener介面,並且重寫該介面提供的所有方法.
* 該JavaBean實現了Serializable(序列化)介面(Session的鈍化與活化是基於Session的序列化實現的)
* Session鈍化與活化和序列化的區別:
* Session序列化:* Tomcat提供的自動機制.
* Session的序列化檔案在重新被使用時,消失.
* Session鈍化與活化:
* 手動實現.
* Session的鈍化檔案並不消失.
* 擴充套件:
* Servlet的三大域物件:
* Request物件 - 一次請求
* Session物件 - 一次會話
* ServletContext物件 - Tomcat從啟動到關閉
* JSP的四大域物件:
* page物件 - 當前頁面
* Request物件
* Session物件
* ServletContext物件
案例:
統計線上人數:
1.建立ServletContextListener監聽器完成線上人數的初始化:
package app.java.listener.demo;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class MyServletContextListener implements ServletContextListener {
/**
* 完成線上人數統計的初始化工作.
*/
public void contextInitialized(ServletContextEvent sce) {
//因為這個監聽器拿不到session,所以就把線上人數放到ServletContext中。
ServletContext context = sce.getServletContext();
context.setAttribute("sums", 0);
}
public void contextDestroyed(ServletContextEvent arg0) {}
}
2.建立HttpSessionListener
package app.java.listener.demo;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class MyHttpSessionListener implements HttpSessionListener {
/**
* 建立Session表示人數增加一個.
* * 在該方法中,獲取ServletContext物件.
* * 修改ServletContext物件的"sums"屬性值.(+1)
* * 將修改後的"sums"屬性值,重新放回去.
*/
public void sessionCreated(HttpSessionEvent se) {
ServletContext context = se.getSession().getServletContext();
int sums = (Integer)context.getAttribute("sums");
sums = sums + 1;
context.setAttribute("sums", sums);
}
/**
* 銷燬Session表示人數減少一個.
* * 在該方法中,獲取ServletContext物件.
* * 修改ServletContext物件的"sums"屬性值.(-1)
* * 將修改後的"sums"屬性值,重新放回去.
*/
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext context = se.getSession().getServletContext();
int sums = (Integer)context.getAttribute("sums");
sums = sums - 1;
context.setAttribute("sums", sums);
}
}
3.建立一個servlet顯示線上人數:
package app.java.listener.demo;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* 當前servlet用於測試統計線上人數
* @author JYL
*/
public class DemoServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("test/html charset = utf-8");
HttpSession session = request.getSession();
session.setAttribute("mingjiao", "zhangwuji");
System.out.println("人數增加了");
// 將統計的線上人數顯示在客戶端頁面 線上人數放在了servletContext裡面
//1 獲取servletContext物件
ServletContext context = getServletContext();
//2 從servletContext物件中,獲取線上統計人數
int sums = (Integer)context.getAttribute("sums");
//3 將線上統計人數響應到客戶端頁面
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("當前線上人數為:"+sums);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
配置xml:
<listener>
<listener-class>app.java.listener.demo.MyServletContextListener</listener-class>
</listener>
<listener>
<listener-class>app.java.listener.demo.MyHttpSessionListener</listener-class>
</listener>