(4)Session(會話)
1)什么是Session?
服務器為了保存用戶狀態而創建的一個特殊的對象。
當瀏覽器第一次訪問服務器時,服務器創建一個session對象(該 對象有一個唯一的id,一般稱之為sessionId),服務器會將sessionId 以cookie的方式發送給瀏覽器。 當瀏覽器再次訪問服務器時,會將sessionId發送過來,服務器依據 sessionId就可以找到對應的session對象。
在 無連接(HTTP)協議基礎之上實現在用戶狀態管理。
2)如何獲得session對象?
方式一 HttpSession s = request.getSession(boolean flag);
注:
HttpSession是一個接口。
當flag為true時: 先查看請求當中是否有sessionId,如果沒有, 則創建一個session對象。如果有,則依據sessionId 查找對應的session對象,如果找到了,則返回該 對象,如果找不到,創建一個新的session對象。 當flag為false時: 先查找請求當中是否有sessionId,如果沒有, 返回null。如果有,則依據sessionId查找對應的session 對象,如果找到了,則返回該對象,如果找不到,返回 null。
方式二 HttpSession s = request.getSession();
等價於 request.getSession(true);
3)常用方法
綁訂數據:
session.setAttribute(String name,Object obj);
依據綁訂名獲得綁訂值:
Object session.getAttribute(String name); 注:如果綁訂名對應的值不存在,返回null。
解除綁訂:
session.removeAttribute(String name);
利用這組方法共享一次會話期間相關的數據。
Session 的銷毀
為了避免Session中存儲的數據過大,Session需要銷毀:
-
超時自動銷毀。
- 從用戶最后一次訪問網站開始,超過一定時間后,服務器自動銷毀Session,以及保存在Session中的數據。
- Tomcat 服務器默認的Session超時時間是30分鍾
-
可以利用web.xml設置超時時間單位是分鍾,設置為0表示不銷毀。
<session-config> <session-timeout>20</session-timeout> </session-config>
-
調用API方法,主動銷毀Session
- session.invalidate()
案例:銷毀Servlet
public class DeleteServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); session.invalidate(); response.setContentType( "text/html; charset=utf-8"); response.getWriter().println("呵呵!"); } }
過濾器 Filter
Servlet 標准中定義了過濾器,可以攔截任意的服務器請求和響應。
實現過濾器的步驟:
- 創建一個過濾器類實現javax.servlet.Filter接口
- 重寫(實現)全部抽象方法
- 業務邏輯寫到 doFilter中
- 如果在doFilter中調用了 chain.doFilter方法則處理后續邏輯,如果不執行這個方法,表示對后續邏輯的攔截。
-
在web.xml(部署描述文件)配置filter,將filter配置到請求之前。
- 可以配置多個filter-mapping,這樣可以復用同一個Filter
- 可以使用 .png 或者 / 過濾一組url
-
當有多個過濾器過濾統一個資源時候,按照配置的先后執行。
<filter-name>demo</filter-name> <filter-class>web.DemoFilter</filter-class> <filter-mapping> <filter-name>demo</filter-name> <url-pattern>/img.png</url-pattern> </filter-mapping>
-
過濾器方法參數 ServletRequest 和 ServletResponse,是 HttpServletRequest 和 HttpServletResponse 的父類型,方法比較少! 如果需要使用HttpServletRequest 和 HttpServletResponse 的方法,需要進行強制類型轉換!
-
比如需要使用 request.getSession() 方法:
HttpServletRequest req = (HttpServletRequest)request; HttpSession session = req.getSession();
-
-
利用 web.xml 可以向Filter 傳遞初始化參數。
<init-param> <param-name>start</param-name> <param-value>8</param-value> </init-param> <init-param> <param-name>end</param-name> <param-value>17</param-value> </init-param> config.getInitParamter("start"); config.getInitParamter("end");
-
Filter 對象的生命周期
- 在Web容器啟動時候創建Filter對象,Filter對象是單例的(只創建一個Filter對象)!
- 創建以后,立即執行init()方法,只執行一次
- 在有url請求時候,會執行匹配的doFilter(),doFilter()是並發執行的。
- Filter對象在容器關閉時候銷毀,銷毀時候執行destroy()
基本過濾器步驟:
-
編寫過濾器類:
/** * 過濾器 Hello World! */ public class DemoFilter implements Filter { public void init(FilterConfig cfg) throws ServletException { } public void destroy() { } public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { req.setAttribute("test", "試試"); System.out.println("Hello World!"); //處理后續請求:如果執行doFilter就正常處理后續 //Web請求和響應,如果不執行doFilter就意味着 //不處理后續請求和響應(也就是請求被攔截了!) chain.doFilter(req, res); } }
-
配置web.xml:
<filter> <filter-name>demo</filter-name> <filter-class>web.DemoFilter</filter-class> </filter> <filter-mapping> <filter-name>demo</filter-name> <url-pattern>/img.png</url-pattern> </filter-mapping> <filter-mapping> <filter-name>demo</filter-name> <url-pattern>/test.html</url-pattern> </filter-mapping> <filter-mapping> <filter-name>demo</filter-name> <url-pattern>*.png</url-pattern> </filter-mapping>
-
測試
多個過濾可以連接使用:
-
編寫Servlet
/** * 演示過濾器執行順序 */ public class TestFilter implements Filter { public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { String test = (String)request.getAttribute("test"); System.out.println("Test Filter:"+test); chain.doFilter(request, response); } public void init(FilterConfig fConfig) throws ServletException { } }
-
配置web.xml:
<filter> <display-name>TestFilter</display-name> <filter-name>TestFilter</filter-name> <filter-class>web.TestFilter</filter-class> </filter> <filter-mapping> <filter-name>TestFilter</filter-name> <url-pattern>*.png</url-pattern> </filter-mapping>
-
測試
利用過濾器限制圖片的訪問:
-
編寫過濾器
public class ImageFilter implements Filter { private int start, end; public void destroy() { System.out.println("我還會回來的!"); } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //獲取當前的時間 Calendar cal = Calendar.getInstance(); //獲取小時分量 int hour = cal.get(Calendar.HOUR_OF_DAY); //在start到下午end之前,可以看見圖片 if(hour>start && hour<end) { chain.doFilter(request, response); }else { response.setContentType( "text/html; charset=UTF-8"); response.getWriter().println("系統繁忙!"); } } public void init(FilterConfig fConfig) throws ServletException { //讀取web.xml文件中的配置參數 String s1=fConfig.getInitParameter("start"); String s2=fConfig.getInitParameter("end"); start = Integer.parseInt(s1); end = Integer.parseInt(s2); System.out.println(start+","+end); } }
-
配置 web.xml
<filter> <display-name>ImageFilter</display-name> <filter-name>ImageFilter</filter-name> <filter-class>web.ImageFilter</filter-class> <init-param> <param-name>start</param-name> <param-value>8</param-value> </init-param> <init-param> <param-name>end</param-name> <param-value>17</param-value> </init-param> </filter> <filter-mapping> <filter-name>ImageFilter</filter-name> <url-pattern>*.png</url-pattern> </filter-mapping>
-
測試
監聽器
在Web容器的工作時候,在出現特定情況下,會自動的執行用戶定義的監聽器程序。利用監聽器程序,可以將用戶程序嵌入到Web容器中工作。
特定情況包括:
- 對象創建情況:
- request對象,response對象,session對象,ServletContext對象等。
- 對象的創建和銷毀時候執行 事件代碼。
- 在對象中添加、刪除數據時候(setAttribute,removeAttribute)
- 其他的工作狀態改變的時候。
如使用: HttpSessionListener
- 創建 類 實現HttpSessionListener
- 重寫方法 sessionCreated()
- 重寫方法 sessionDestroyed()
- 在web.xml 中配置
- 啟動web容器
- 當web容器工作期間創建了session對象時候,會自動執行 sessionCreated()
- 當web容器工作期間銷毀了session對象時候, 會自動執行sessionDestroyed()
案例:
/** * 監聽器演示案例 */ public class DemoListener implements HttpSessionListener { //在Session對象創建以后執行 public void sessionCreated(HttpSessionEvent e) { System.out.println("Hello Session Created"); //e 代表當前事件發生時候的相關數據。 HttpSession s = e.getSession(); System.out.println("SID:"+s.getId()); } //在Session對象銷毀以后執行 public void sessionDestroyed(HttpSessionEvent e) { System.out.println("Hello Session Destroyed"); } } <listener> <listener-class>web.DemoListener</listener-class> </listener>
如上功能的意義:在session創建銷毀時候插入用戶自定義的代碼。
最重要的監聽器:ServletContextListener
- contextInitialized() 會在Web服務器啟動時候執行。 在軟件中需要初始化的程序寫到這個方法中。
- contextDestoryed() 會在Web服務器關閉時候執行。如果需要在關閉時候清除的資源,可以寫到這個方法中。
案例:
public class InitListener implements ServletContextListener { //在web服務器關閉時候執行 public void contextDestroyed(ServletContextEvent e) { System.out.println("Hello contextDestroyed"); } //在web服務器啟動時候執行,用於初始化資源 public void contextInitialized(ServletContextEvent e) { System.out.println("Hello contextInitialized"); } } <listener> <listener-class>web.InitListener</listener-class> </listener>