Listener & Filter
Listener
監聽器:監聽某一個事件的發生,狀態的改變
監聽器的內部機制:其實就是介面回撥
介面回撥:
需求:
A在執行迴圈,當迴圈到5的時候,通知B。
事先先把一個物件傳遞給A,當A執行到5的時候,通過這個物件,來呼叫B中的方法。但是注意,不是直接傳遞B的例項,而是傳遞一個介面的例項過去。
A和B兩者中間藉助介面去聯絡上。
所以一開始在執行A的print方法時,先把一個介面的實現類傳遞給A,後面A在根據這個物件,在呼叫B的方法。
Web監聽器:
總共有8個 劃分為三種類型
1.定義一個類,實現介面
2.註冊| 配置監聽器
1.監聽三個作用域建立和銷燬
request ---httpServletRequest
session ---httpSession
application --- ServletContext
1.ServletContextListener
servletcontext建立:
1.啟動伺服器的時候
servletContext銷燬:
2.關閉伺服器,從伺服器移除專案
2.ServletRequestListener
request建立:
訪問伺服器上的任意資源都會有請求出現
訪問html、jsp、servlet
request銷燬:
伺服器已經對這次請求作出了響應
3.HttpSessionListener
session的建立
只要呼叫getSession
html:不會
jsp:會 getSession();
servlet : 會
session的銷燬
超時 30分鐘
非正常關閉 銷燬
正常關閉伺服器(序列化)
作用:
ServletContextListener
利用它來,在servletcontext建立的時候,
1.完成自己想要的初始化工作
2.執行自定義任務排程。執行某一個任務。Timer
HttpSessionListener
統計線上人數。
2.監聽三個作用域屬性狀態變更
request --- ServletRequestAttributeListener
session --- HttpSessionAttributeListener
servletContext --- ServletContextAttributeListener
>可以監聽在作用域中值 新增 | 替換 | 移除的動作。
3.監聽httpSession裡面存值的狀態變更
這一類監聽器不用註冊。
HttpSessionBindingListener
>監聽物件與session 繫結和解除繫結 的動作
1.讓javaBean實現該介面即可
HttpSessionActivationListener
>用於監聽現在session的值 是 鈍化(序列化)還是活化(反序列化)的動作
鈍化(序列化):把記憶體中的資料 儲存到硬碟上
活化(反序列化):把硬碟中的資料讀取到記憶體中
session的鈍化活化的用意:
session中的值可能會很多,並且我們有很長一段時間不使用這個 記憶體中的值,那麼可以考慮把session的值可以儲存到硬碟上【鈍化】,等下一次在使用的時候,在從硬碟上提取出來。【活化】
如何讓session在一定時間內鈍化:
做配置即可:
在自己的web工程專案中的META-INF/context.xml,只對當前的工程生效。
maxIdleSwap:1分鐘不用就鈍化
directory:鈍化後的那個檔案存放的目錄位置
<Context>
<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
<Store className="org.apache.catalina.session.FileStore" directory="it315"/>
</Manager>
</Context>
Filter:
過濾器,其實就是對客戶端發出來的請求進行過濾,瀏覽器發出,然後伺服器派servlet處理。在中間就可以過濾,其實過濾器起到的是攔截的作用。
作用:1.對一些敏感詞彙進行過濾
2.統一設定編碼
3.自動登入
如何使用Filter:
1.定義一個類,實現Filter
2.註冊過濾器
在web.xml裡面註冊,註冊的手法與servlet基本一樣
Filter的生命週期:
建立:在伺服器啟動的時候就建立
銷燬:伺服器停止的時候
Filter執行順序:
1.客戶端發出請求,先經過過濾器,如果過濾器放行,那麼才能到servlet
2.如果有多個過濾器,那麼他們會按照註冊的對映順序來排隊。只要有一個過濾器,不放行,那麼後面排隊的過濾器以及咱們的servlet都不會收到請求。
細節:
1.init方法的引數 FilterConfig
2.在doFilter方法裡面操作,使用引數chain chain.doFilter(request,response);放行,讓請求到達下一個目標
3.<url-pattern>/*</url-pattern>
1.全路徑匹配 以/開始 /LoginServlet
2.以目錄匹配 以/開始 以*結束 /demo01/*
3.以後綴名匹配 以*開始 以後綴名結束 *.jsp *.html *.do
4.針對dispatcher設定
自動登入:
BeanUtilsDemo:
try {
Map map = request.getParameterMap();
UserBean bean = new UserBean();
BeanUtils.populate(bean, map);
System.out.println("2222bean="+bean.toString());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
//註冊自己的日期轉換器
ConvertUtils.register(new MyDateConverter(), Date.class);
Map map = request.getParameterMap();
UserBean bean = new UserBean();
//轉化map中的資料,放置到bean物件上
BeanUtils.populate(bean, map);
System.out.println("2222bean="+bean.toString());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
過濾器程式碼:
1.先判斷session是否有效,如果有效,就不用取cookie了,直接放行
2.如果session失效了,那麼就取cookie
1.沒有cookie 放行
2.有cookie
1.取出來cookie的值,然後完成登入
2.把這個使用者的值儲存到session中
3.放行
public void doFilter(ServletRequest req, ServletResponse response, FilterChain chain) throws IOException, ServletException {
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();
try {
userBean = dao.login(user);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
chain.doFilter(request, response);
}
//使用session存這個值到域中,方便下一次未過期前還可以用
request.getSession().setAttribute("userBean", userBean);
chain.doFilter(request, response);
}
}
}
servlet:
public class LoginServlet extends HttpServlet {
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");
//System.out.println(username + "=" + password+"="+autoLogin);
UserBean user = new UserBean();
user.setUsername(username);
user.setPassword(password);
UserDao dao = new UserDaoImpl();
UserBean userBean = dao.login(user);
System.out.println("有");
if(userBean != null) {
//頁面提交上來的時候,是否選擇了自動登入
if("on".equals(autoLogin))
{
//傳送cookie給客戶端
Cookie cookie = new Cookie("auto_login", username+"#itheima#"+password);
cookie.setMaxAge(60*60*24*7);
cookie.setPath(request.getContextPath());
response.addCookie(cookie);
}
//成功了,進入首頁
request.getSession().setAttribute("userBean", userBean);
response.sendRedirect("index.jsp");
}
else
{
//不成功
request.getRequestDispatcher("login.jsp").forward(request, response);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}