JavaWeb基礎之Listener和Filter
Listener
監聽器
- 能做什麼事?
監聽某一個事件的發生, 狀態的改變。
- 監聽器的內部機制
其實就是介面回撥.
介面回撥
- 需求:
A在執行迴圈,當迴圈到5的時候, 通知B。
事先先把一個物件傳遞給 A , 當A 執行到5的時候,通過這個物件,來呼叫B中的方法。 但是注意,不是直接傳遞B的例項,而是傳遞一個介面的例項過去。
Web監聽器
總共有8個 劃分成三種類型
-
定義一個類,實現介面
-
註冊 | 配置監聽器
監聽三個作用域建立和銷燬
request ---httpServletRequest session ---httpSession aapplication --- ServletContext 1. ServletContextListener servletcontext建立: 1. 啟動伺服器的時候 servletContext銷燬: 2. 關閉伺服器. 從伺服器移除專案 2. ServletRequestListener request建立: 訪問伺服器上的任意資源都會有請求出現。 訪問 html: 會 訪問 jsp: 會 訪問 servlet : 會 request銷燬: 伺服器已經對這次請求作出了響應。 public class MyRequestListener implements ServletRequestListener { @Override public void requestDestroyed(ServletRequestEvent sre) { System.out.println("servletrequest 銷燬了"); } @Override public void requestInitialized(ServletRequestEvent sre) { System.out.println("servletrequest 初始化了"); } } <listener> <listener-class>com.itheima.listener.MyRequestListener</listener-class> </listener> 3. HttpSessionListener session的建立 只要呼叫getSession html: 不會 jsp: 會 getSession(); servlet: 會 session的銷燬 超時 30分鐘 非正常關閉 銷燬 正常關閉伺服器(序列化) public class MySessionListener implements HttpSessionListener { @Override public void sessionCreated(HttpSessionEvent se) { System.out.println("建立session了"); } @Override public void sessionDestroyed(HttpSessionEvent se) { System.out.println("銷燬session了"); } }
作用:
ServletContextListener
利用它來,在servletcontext建立的時候,
1. 完成自己想要的初始化工作
2. 執行自定義任務排程。 執行某一個任務。 Timer
HttpSessionListener
統計線上人數.
監聽三個作用域屬性狀態變更
可以監聽在作用域中值 新增 | 替換 | 移除的動作。
-
servletContext — ServletContextAttributeListener
-
request — ServletRequestAttributeListener
-
session — HttpSessionAttributeListener
監聽httpSession裡面存值的狀態變更
這一類監聽器不用註冊。
- HttpSessionBindingListener
監聽物件與session 繫結和解除繫結 的動作
1. 讓javaBean 實現該介面即可
@Override
public void valueBound(HttpSessionBindingEvent event) {
System.out.println("物件被繫結進來了");
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
System.out.println("物件被解除繫結");
}
- HttpSessionActivationListener
用於監聽現在session的值 是 鈍化 (序列化)還是活化 (反序列化)的動作
- 鈍化 (序列化)
把記憶體中的資料 儲存到硬碟上
- 活化 (反序列化)
把硬碟中的資料讀取到記憶體中。
- session的鈍化活化的用意何在
session中的值可能會很多, 並且我們有很長一段時間不使用這個記憶體中的值, 那麼可以考慮把session的值可以儲存到硬碟上【鈍化】,等下一次在使用的時候,在從硬碟上提取出來。 【活化】
- 如何讓session的在一定時間內鈍化.
做配置即可
1. 在tomcat裡面 conf/context.xml 裡面配置
對所有的執行在這個伺服器的專案生效
2. 在conf/Catalina/localhost/context.xml 配置
對 localhost生效。 localhost:8080
3. 在自己的web工程專案中的 META-INF/context.xml
只對當前的工程生效。
maxIdleSwap : 1分鐘不用就鈍化
directory : 鈍化後的那個檔案存放的目錄位置。
D:\tomcat\apache-tomcat-7.0.52\work\Catalina\localhost\ListenerDemo\itheima
<Context>
<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
<Store className="org.apache.catalina.session.FileStore" directory="itheima"/>
</Manager>
</Context>
Filter
過濾器 , 其實就是對客戶端發出來的請求進行過濾。 瀏覽器發出, 然後伺服器派servlet處理。 在中間就可以過濾, 其實過濾器起到的是攔截的作用。
-
作用
- 對一些敏感詞彙進行過濾
- 統一設定編碼
- 自動登入
…
如何使用Filter
-
定義一個類, 實現Filter
public class FilterDemo implements Filter { public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("來到過慮器了。。。"); chain.doFilter(request, response); } public void init(FilterConfig fConfig) throws ServletException { } }
-
註冊過濾器
在web.xml裡面註冊,註冊的手法與servlet基本一樣。
<filter>
<display-name>FilterDemo</display-name>
<filter-name>FilterDemo</filter-name>
<filter-class>com.itheima.filter.FilterDemo</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterDemo</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Filter的生命週期
- 建立
在伺服器啟動的時候就建立。
- 銷燬
伺服器停止的時候。
Filter執行順序
-
客戶端發出請求,先經過過濾器, 如果過濾器放行,那麼才能到servlet
-
如果有多個過濾器, 那麼他們會按照註冊的對映順序 來 排隊。 只要有一個過濾器, 不放行,那麼後面排隊的過濾器以及咱們的servlet都不會收到請求。
Filter細節:
-
init方法的引數 FilterConfig , 可以用於獲取filter在註冊的名字 以及初始化引數。 其實這裡的設計的初衷與ServletConfig是一樣的。
-
如果想放行,那麼在doFilter 方法裡面操作,使用引數 chain
chain.doFilter(request, response); 放行, 讓請求到達下一個目標。
-
/* 寫法格式與servlet一樣。
-
全路徑匹配 以 / 開始
/LoginServlet
-
以目錄匹配 以 / 開始 以 * 結束
/demo01/*
-
以後綴名匹配 以 * 開始 以後綴名結束
*.jsp *.html *.do
-
-
針對 dispatcher 設定
REQUEST : 只要是請求過來,都攔截,預設就是REQUEST FORWARD : 只要是轉發都攔截。 ERROR : 頁面出錯發生跳轉 INCLUDE : 包含頁面的時候就攔截。
自動登入
- 需求分析
1. 搭建環境
-
搭建資料庫
-
搭建頁面
登入servlet程式碼
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
String userName = request.getParameter("username");
String password = request.getParameter("password");
String autoLogin = request.getParameter("auto_login");
UserBean user = new UserBean();
user.setUsername(userName);
user.setPassword(password);
UserDao dao = new UserDaoImpl();
UserBean userBean = dao.login(user);
if(userBean != null){
//成功了,進入首頁
request.getSession().setAttribute("userBean", userBean);
response.sendRedirect("index.jsp");
}else{
//不成功...
request.getRequestDispatcher("login.jsp").forward(request, response);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
過濾器程式碼
過濾器的核心不是完成攔截 , 不是放行顯示。 它的核心是在放行之前,幫使用者完成登入的功能。
- 實現思路
-
先判斷session是否有效, 如果有效,就不用取cookie了,直接放行。
-
如果session失效了,那麼就取 cookie。
-
沒有cookie 放行
-
有cookie
1. 取出來cookie的值,然後完成登入 2. 把這個使用者的值儲存到session中 3. 放行。 /** * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain) */ public void doFilter(ServletRequest req, ServletResponse response, FilterChain chain) throws IOException, ServletException { try { HttpServletRequest request = (HttpServletRequest) req; //先判斷,現在session中還有沒有那個userBean. UserBean userBean = (UserBean) request.getSession().getAttribute("userBean"); //還有,有效。 if(userBean != null){ chain.doFilter(request, response); }else{ //代表session失效了。 //2. 看cookie。 //1. 來請求的時候,先從請求裡面取出cookie , 但是cookie有很多的key-value Cookie[] cookies = request.getCookies(); //2. 從一堆的cookie裡面找出我們以前給瀏覽器發的那個cookie Cookie cookie = CookieUtil.findCookie(cookies, "auto_login"); //第一次來 if(cookie == null){ chain.doFilter(request, response); }else{ //不是第一次。 String value = cookie.getValue(); String username = value.split("#itheima#")[0]; String password = value.split("#itheima#")[1]; //完成登入 UserBean user = new UserBean(); user.setUsername(username); user.setPassword(password); UserDao dao = new UserDaoImpl(); userBean = dao.login(user); //使用session存這個值到域中,方便下一次未過期前還可以用。 request.getSession().setAttribute("userBean", userBean); chain.doFilter(request, response); } } } catch (Exception e) { e.printStackTrace(); chain.doFilter(req, response); } }
-
BeanUtils的使用
BeanUtils.populate(bean, map);
//註冊自己的日期轉換器
ConvertUtils.register(new MyDateConverter(), Date.class);
//轉化資料
Map map = request.getParameterMap();
UserBean bean = new UserBean();
轉化map中的資料,放置到bean物件身上
BeanUtils.populate(bean, map);
總結
Listener
8個
三種類型
針對三個作用域的建立和銷燬
針對三個作用域的值改變 【新增 | 替換 | 移除】
針對session中的值 【鈍化 活化】 , 【繫結 解綁】
鈍化 ( 序列化 )
記憶體中的物件儲存到硬碟
超時失效。 session銷燬了。
非正常關閉伺服器, 鈍化 。 正常關閉伺服器 銷燬
設定了session,多久時間。 context.xml
活化 (反序列化)
從硬盤裡面讀取到記憶體
ServletContextListner : 應用被部署的時候, 伺服器載入這個專案的時候,做一些初始化工作, 任務排程。
HttpSessionListener : 統計線上人數
HttpSessionActivationListener : 鈍化活化處理
Filter
使用頻率更高
- 如果要寫一個過濾器。
- 定義一個類,實現介面 Filter
- 註冊 . web.xml . 與servlet相似。
- 過濾器放行。
chain.doFilter(request, response);
-
過濾器生命週期
建立: 伺服器載入這個專案的時候建立例項
銷燬: 關閉伺服器或者從伺服器中移除專案的時候。