##Listener
> 監聽器
* 能做什么事?
> 監聽某一個事件的發生。 狀態的改變。
* 監聽器的內部機制
> 其實就是接口回調.
####接口回調
* 需求:
> A在執行循環,當循環到5的時候, 通知B。
> 事先先把一個對象傳遞給 A , 當A 執行到5的時候,通過這個對象,來調用B中的方法。 但是注意,不是直接傳遞B的實例,而是傳遞一個接口的實例過去。
?
###Web監聽器
> 總共有8個 劃分成三種類型
1. 定義一個類,實現接口
2. 注冊 | 配置監聽器
### 監聽三個作用域創建和銷毀
request ---httpServletRequest
session ---httpSession
aapplication --- ServletContext
1. ServletContextListener
? ? ? ? ? ? ? servletcontext創建:啟動服務器的時候
? ? ? ? ? ? ? servletContext銷毀:?關閉服務器. 從服務器移除項目
?
import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener;public class MyServletContextListener implements ServletContextListener{public void contextDestroyed(ServletContextEvent arg0) {// TODO Auto-generated method stubSystem.out.println("初始化......");}public void contextInitialized(ServletContextEvent arg0) {// TODO Auto-generated method stubSystem.out.println("銷毀了......");}}
?
?
注冊代碼:
ServletContextListener 監聽器的配置<listener><listener-class>com.zyz.listener.MyServletContextListener</listener-class> </listener>
?
?
?
2. ServletRequestListener
request創建:訪問服務器上的任意資源都會有請求出現。
? ? ? ? ? ? ?訪問 html: 會
? ? ? ? ? ? ?訪問 jsp: 會
? ? ? ? ? ? ?訪問 servlet : 會
request銷毀:服務器已經對這次請求作出了響應。
import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestListener;public class MyServletRequestListener implements ServletRequestListener {public void requestDestroyed(ServletRequestEvent arg0) {// TODO Auto-generated method stubSystem.out.println("servletrequest 銷毀了");}public void requestInitialized(ServletRequestEvent arg0) {// TODO Auto-generated method stubSystem.out.println("servletrequest 初始化了");}/** servletrequest 初始化了servletrequest 銷毀了*/}
?
注冊代碼:
ServletRequestListener 監聽器配置<listener><listener-class>com.zyz.listener.MyServletRequestListener</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處理。 在中間就可以過濾, 其實過濾器起到的是攔截的作用。
* 作用
1. 對一些敏感詞匯進行過濾
2. 統一設置編碼
3. 自動登錄
...
###如何使用Filter
1. 定義一個類, 實現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 {
}
}
2. 注冊過濾器
> 在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執行順序
1. 客戶端發出請求,先經過過濾器, 如果過濾器放行,那么才能到servlet
2. 如果有多個過濾器, 那么他們會按照注冊的映射順序 來 排隊。 只要有一個過濾器, 不放行,那么后面排隊的過濾器以及咱們的servlet都不會收到請求。
##Filter細節:
1. init方法的參數 FilterConfig , 可以用于獲取filter在注冊的名字 以及初始化參數。 其實這里的設計的初衷與ServletConfig是一樣的。
2. 如果想放行,那么在doFilter 方法里面操作,使用參數 chain
chain.doFilter(request, response); 放行, 讓請求到達下一個目標。
3. <url-pattern>/*</url-pattern> 寫法格式與servlet一樣。
1. 全路徑匹配 以 / 開始
/LoginServlet
2. 以目錄匹配 以 / 開始 以 * 結束
/demo01/* 攔截文件夾demo01下的所有
3. 以后綴名匹配 以 * 開始 以后綴名結束 (例如*.jsp攔截所有的jsp文件)
*.jsp *.html *.do
4. 針對 dispatcher 設置
REQUEST : 只要是請求過來,都攔截,默認就是REQUEST
FORWARD : 只要是轉發都攔截。
ERROR : 頁面出錯發生跳轉
INCLUDE : 包含頁面的時候就攔截。
###自動登錄
* 需求分析
####1. 搭建環境
1. 搭建數據庫
2. 搭建頁面
###登錄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();
}
}
##過濾器代碼
> 過濾器的核心不是完成攔截不給 , 還是放行顯示。 它的核心是在放行之前,幫用戶完成登錄的功能。
* 實現思路
1. 先判斷session是否有效, 如果有效,就不用取cookie了,直接放行。
2. 如果session失效了,那么就取 cookie。
1. 沒有cookie 放行
2. 有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
> 使用頻率更高
* 如果要寫一個過濾器。
> 1. 定義一個類,實現接口 Filter
> 2. 注冊 . web.xml . 與servlet相似。
* 過濾器放行。
> chain.doFilter(request, response);
* 過濾器生命周期
創建: 服務器加載這個項目的時候創建實例
銷毀: 關閉服務器或者從服務器中移除項目的時候。