最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java Listener監(jiān)聽器使用規(guī)范詳細介紹

 更新時間:2023年01月13日 10:24:59   作者:@每天都要敲代碼  
監(jiān)聽器是一個專門用于對其他對象身上發(fā)生的事件或狀態(tài)改變進行監(jiān)聽和相應處理的對象,當被監(jiān)視的對象發(fā)生情況時,立即采取相應的行動。監(jiān)聽器其實就是一個實現(xiàn)特定接口的普通java程序,這個程序專門用于監(jiān)聽另一個java對象的方法調用或屬性改變

1、什么是監(jiān)聽器以及監(jiān)聽器作用

①監(jiān)聽器是Servlet規(guī)范中的一員。就像Filter一樣。Filter也是Servlet規(guī)范中的一員。

②在Servlet中,所有的監(jiān)聽器接口都是以“Listener”結尾。

③監(jiān)聽器實際上是Servlet規(guī)范留給我們javaweb程序員的特殊時機。

④特殊的時刻如果想執(zhí)行這段代碼,你需要想到使用對應的監(jiān)聽器。

2、Servlet規(guī)范中提供了哪些監(jiān)聽器

javax.servlet包下:

①ServletContextListener

②ServletContextAttributeListener

③ServletRequestListener

④ServletRequestAttributeListener

jakarta.servlet.http包下:

①HttpSessionListener

②HttpSessionAttributeListener

③HttpSessionBindingListener

④HttpSessionIdListener

⑤HttpSessionActivationListener

3、實現(xiàn)一個監(jiān)聽器的步驟

這里主要先講解熟悉的關于三個域對象的監(jiān)聽器:

ServletContext、ServletRequest、HttpSession

(1)以ServletContextListener為例

①第一步:編寫一個類實現(xiàn)ServletContextListener接口。并且實現(xiàn)里面的方法。

監(jiān)聽器中的方法不需要程序員手動調用。是發(fā)生某個特殊事件之后被服務器調用。

// ServletContext對象被創(chuàng)建的時候調用。
void contextInitialized(ServletContextEvent event)
// ServletContext對象被銷毀的時候調用
void contextDestroyed(ServletContextEvent event)

②第二步:在web.xml文件中對ServletContextListener進行配置,如下:

當然,第二步也可以不使用配置文件,也可以用注解,例如:@WebListener 即可。

   <listener>
        <listener-class>com.bjpowernode.javaweb.servlet.MyServletContextListener</listener-class>
    </listener>

注意:所有監(jiān)聽器中的方法都是不需要javaweb程序員調用的,由服務器來負責調用。

什么時候被調用呢?當某個特殊的事件發(fā)生(特殊的事件發(fā)生其實就是某個時機到了)之后,被web服務器自動調用。

③服務器啟動時,ServletContext對象創(chuàng)建,contextInitialized方法執(zhí)行

服務器關閉時,ServletContext對象銷毀,contextDestroyed方法執(zhí)行

package com.bjpowernode.javaweb.servlet;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
 * @Package:com.bjpowernode.javaweb.servlet
 * @Project:JavaWeb
 * @name:MyServletContextListener
 */
// ServletContextListener監(jiān)聽器主要監(jiān)聽的是:ServletContext對象的狀態(tài)。
public class MyServletContextListener implements ServletContextListener { // 服務器啟動時間點
    /**
     * 監(jiān)聽器中的方法不需要程序員手動調用。是發(fā)生某個特殊事件之后被服務器調用。
     * @param sce
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) { // 服務器關閉時間點
        // 現(xiàn)在這個特殊的時刻寫代碼,你寫就是了。它會被服務器自動調用。
        // 這個方法是在ServletContext對象被創(chuàng)建的時候調用。
        System.out.println("ServletContext對象創(chuàng)建了。");
    }
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // 現(xiàn)在這個特殊的時刻寫代碼,你寫就是了。它會被服務器自動調用。
        // 這個方法是在ServletContext對象被銷毀的時候調用。
        System.out.println("ServletContext對象被銷毀了。");
    }
}

(2)以ServletRequestListener為例

④ServletRequest對象是一次請求創(chuàng)建一個request對象,所以服務器啟動后:

只要發(fā)送一次請求就會調用requestInitialized方法,請求結束立刻會調用requestDestroyed

注:我們直接訪問http://localhost:8080/servlet15/會報404錯誤,因為默認會訪問index.html,但是我們并沒有寫;就算如此也會發(fā)送出請求,執(zhí)行這個監(jiān)聽器。

package com.bjpowernode.javaweb.servlet;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
/**
 * @Package:com.bjpowernode.javaweb.servlet
 * @Project:JavaWeb
 * @name:MyServletRequestListener
 */
@WebListener
public class MyServletRequestListener implements ServletRequestListener {
    // request對象銷毀時間點
    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("request對象銷毀了");
    }
    // request對象創(chuàng)建時間點
    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("request對象初始化了");
    }
}

(3)以HttpSessionListener為例

⑤我們都知道在訪問jsp時,默認會創(chuàng)建session對象(九大內置對象);先編寫一個my.jsp;在訪問my.jsp時,會創(chuàng)建session對象,調用 sessionCreated方法;

當退出系統(tǒng)時,我們編寫銷毀session對象的方法,會調用sessionDestroyed方法。

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
my jsp page
<a href="${pageContext.request.contextPath}/exit" rel="external nofollow" >退出系統(tǒng)</a>
</body>
</html>

根據(jù)/exit請求,編寫銷毀session對象的類

package com.bjpowernode.javaweb;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
 * @Package:com.bjpowernode.javaweb
 * @Project:JavaWeb
 * @name:ExitServlet
 */
@WebServlet("/exit")
public class ExitServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 獲取session對象
        HttpSession session = request.getSession(false);
        if (session != null) {
            // 銷毀session
            session.invalidate();
        }
    }
}

(4)AttributeListener的使用

①我們知道對于域對象都有setAttribute、getAttribute、removeAttribute方法,分別可以向域中存數(shù)據(jù)、取數(shù)據(jù)、清除數(shù)據(jù);所以對于AttributeListener肯定是和這些處理域中數(shù)據(jù)有關。

②實際上對于ServletContextAttributeListener、ServletRequestAttributeListener 、HttpSessionAttributeListener這三個對象都有attributeAdded、attributeRemoved、attributeReplaced方法;表示:向域當中存儲數(shù)據(jù)的時候調用、向域當中刪除數(shù)據(jù)的時候調用、向域當中替換數(shù)據(jù)的時候調用。

③這里以HttpSessionAttributeListener對象為例:

編寫HttpSessionAttributeListener監(jiān)聽器

package com.bjpowernode.javaweb.servlet;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
/**
 * @Package:com.bjpowernode.javaweb.servlet
 * @Project:JavaWeb
 * @name:MyHttpSessionAttributeListener
 */
@WebListener
public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener {
    // 向session域當中存儲數(shù)據(jù)的時候,以下方法被WEB服務器調用。
    @Override
    public void attributeAdded(HttpSessionBindingEvent se) {
        System.out.println("session data add");
    }
    // 將session域當中存儲的數(shù)據(jù)刪除的時候,以下方法被WEB服務器調用。
    @Override
    public void attributeRemoved(HttpSessionBindingEvent se) {
        System.out.println("session data remove");
    }
    // session域當中的某個數(shù)據(jù)被替換的時候,以下方法被WEB服務器調用。
    @Override
    public void attributeReplaced(HttpSessionBindingEvent se) {
        System.out.println("session data replace");
    }
}

編寫Servlet類用來處理域中的數(shù)據(jù)

當發(fā)送http://localhost:8080/servlet15/session/attribute/test就能觸發(fā)上面的監(jiān)聽器;

注意:調用getAttribute方法不會觸發(fā),只有setAttribute方法和removeAttribute方法才會觸發(fā)

package com.bjpowernode.javaweb;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
 * @Package:com.bjpowernode.javaweb
 * @Project:JavaWeb
 * @name:HttpSessionAttributeServlet
 */
@WebServlet("/session/attribute/test")
public class HttpSessionAttributeServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 獲取session對象
        HttpSession session = request.getSession();
        // 向session域中存儲數(shù)據(jù)
        session.setAttribute("user", "zhangsan");
        // 替換,覆蓋上面的數(shù)據(jù)
        session.setAttribute("user", "lisi");
        // 刪除
        session.removeAttribute("user");
    }
}

4、HttpSessionBindingListener

(1)前面我們已經(jīng)講解了關于域對象的監(jiān)聽器,九個監(jiān)聽器中就已經(jīng)學習了6個;接下來就先分析一下HttpSessionBindingListener;顧名思義就是關于數(shù)據(jù)綁定的!

(2)下面就通過一個例子來學習一下HttpSessionBindingListener監(jiān)聽器:

創(chuàng)建一個user1類實現(xiàn)監(jiān)聽器(不需要@WebListener注解),并重寫方法

創(chuàng)建一個user2類不實現(xiàn)監(jiān)聽器

對比當數(shù)據(jù)放入放入域當中,兩者會有什么區(qū)別:

①普通的user1類實現(xiàn)監(jiān)聽器,并重寫監(jiān)聽器中兩個方法

package com.bjpowernode.javaweb.bean;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
/**
 * 普通的java類。但是它實現(xiàn)了:HttpSessionBindingListener
 */
public class User1 implements HttpSessionBindingListener {
    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        System.out.println("綁定數(shù)據(jù)");
    }
    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        System.out.println("解綁數(shù)據(jù)");
    }
    private String usercode;
    private String username;
    private String password;
    public User1(String usercode, String username, String password) {
        this.usercode = usercode;
        this.username = username;
        this.password = password;
    }
    public User1() {
    }
    public String getUsercode() {
        return usercode;
    }
    public void setUsercode(String usercode) {
        this.usercode = usercode;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

②普通的user2類不實現(xiàn)監(jiān)聽器

package com.bjpowernode.javaweb.bean;
/**
 * 普通的java類。
 */
public class User2 {
    private String usercode;
    private String username;
    private String password;
    public User2() {
    }
    public User2(String usercode, String username, String password) {
        this.usercode = usercode;
        this.username = username;
        this.password = password;
    }
    public String getUsercode() {
        return usercode;
    }
    public void setUsercode(String usercode) {
        this.usercode = usercode;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

③編寫一個servlet類,把這兩種數(shù)據(jù)都存進去

發(fā)現(xiàn)實現(xiàn)監(jiān)聽器的user1類會觸發(fā)綁定事件!

package com.bjpowernode.javaweb.servlet;
import com.bjpowernode.javaweb.bean.User1;
import com.bjpowernode.javaweb.bean.User2;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/session/bind")
public class HttpSessionBindingListenerServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 獲取session對象
        HttpSession session = request.getSession();
        // 準備兩個對象:User1 User2
        User1 user1 = new User1("111", "zhangsan", "123");
        User2 user2 = new User2("111", "zhangsan", "123");
        // 將user1存儲到session域
        session.setAttribute("user1", user1);
        // 將user2存儲到session域
        session.setAttribute("user2", user2);
    }
}

(3)區(qū)分:HttpSessionAttributeListener 和HttpSessionBindingListener

??HttpSessionAttributeListener監(jiān)聽器

①該監(jiān)聽器是需要使用@WebListener注解進行標注的(或者使用web.xml文件進行配置)

②該監(jiān)聽器監(jiān)聽的是session域中數(shù)據(jù)的變化。只要數(shù)據(jù)變化,則執(zhí)行相應的方法;主要監(jiān)測點在session域對象上。

③監(jiān)聽的是session域,只要把數(shù)據(jù)放入session域就進行監(jiān)聽!

??HttpSessionBindingListener監(jiān)聽器

①該監(jiān)聽器是不需要使用@WebListener進行標注,類直接實現(xiàn)即可。

②假設User類實現(xiàn)了該監(jiān)聽器,那么User對象在被放入session的時候觸發(fā)bind事件,User對象從session中刪除的時候,觸發(fā)unbind事件。

③假設Customer類沒有實現(xiàn)該監(jiān)聽器,那么Customer對象放入session或者從session刪除的時候,不會觸發(fā)bind和unbind事件。

④監(jiān)聽的是普通的java對象,那個類實現(xiàn)了這個監(jiān)聽器,就監(jiān)聽那個類!

??總結:

①對于HttpSessionAttributeListener監(jiān)聽的是任何種類的對象,只要放入session域當中就可以;上述user1和user2都可以觸發(fā)!

②對于HttpSessionBindingListener監(jiān)聽的是特殊的對象,只有實現(xiàn)HttpSessionBindingListener接口的才可以;上述只有user1才能觸發(fā)!

(4)那么這兩個監(jiān)聽器有什么用呢?

我們通過一個簡單的業(yè)務需求了解一下:

業(yè)務1:編寫一個功能,記錄該網(wǎng)站實時的在線用戶的個數(shù)

我們可以通過服務器端有沒有分配session對象,因為一個session代表了一個用戶。有一個session就代表有一個用戶。如果你采用這種邏輯去實現(xiàn)的話,session有多少個,在線用戶就有多少個。這種方式的話:HttpSessionListener夠用了。session對象只要新建,則count++,然后將count存儲到ServletContext域當中,在頁面展示在線人數(shù)即可!

業(yè)務2:只統(tǒng)計登錄的用戶的在線數(shù)量

用戶登錄的標志是什么?session中曾經(jīng)存儲過User類型的對象。那么這個時候可以讓User類型的對象實現(xiàn)HttpSessionBindingListener監(jiān)聽器,只要User類型對象存儲到session域中,則count++,然后將count++存儲到ServletContext對象中。頁面展示在線人數(shù)即可。

5、HttpSessionIdListener&HttpSessionActivationListener

這兩個監(jiān)聽器不常用,這里只簡單了解即可:

(1)HttpSessionIdListener:session的id發(fā)生改變的時候,監(jiān)聽器中的唯一一個方法就會被調用。

(2)HttpSessionActivationListener:監(jiān)聽session對象的鈍化和活化的。

①鈍化:session對象從內存存儲到硬盤文件。

②活化:從硬盤文件把session恢復到內存。

6、使用監(jiān)聽器統(tǒng)計網(wǎng)站在線人數(shù)

實現(xiàn)oa項目中當前登錄在線的人數(shù)!

(1)什么代表著用戶登錄了?

??session.setAttribute("user", userObj); User類型的對象只要往session中存儲過,表示有新用戶登錄。

(2)什么代表著用戶退出了?

??session.removeAttribute("user"); User類型的對象從session域中移除了。

??或者有可能是session銷毀了。(session超時) 。

(3)思考:我們要先思考一下尋訪到什么域里面?

統(tǒng)計這個項目當匯總的登錄在線人數(shù),一個人一個的(session)以下的域肯定都不行,所以只能使用application域(ServletContext)。

①編寫User類實現(xiàn)監(jiān)聽器的接口;然后修改關于所有session.getAttribute的代碼

package com.bjpowernode.oa.bean;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
/**
 * @Package:com.bjpowernode.oa.bean
 * @Project:JavaWeb
 * @name:User
 */
public class User implements HttpSessionBindingListener {
    // 重寫兩個方法
    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        // 用戶登錄了
        // 相當于User類型的對象向session域當中存放
        // 獲取application域對象
        // event.getSession()獲取到session;在調用getServletContext()獲取到域對象
        ServletContext application = event.getSession().getServletContext();
        // 獲取到在線人數(shù)
        Object onlioncount = application.getAttribute("onlioncount");
        // 第一個用戶登錄,里面什么都沒有,返回的是一個null
        if (onlioncount == null) {
            application.setAttribute("onlioncount",1);
        }else {
            // 直接 onlioncount++有問題,前面是Object類型,強轉
            Integer count = (Integer)onlioncount;
            count++;
            // 在存入域當中
            application.setAttribute("onlioncount",count);
        }
    }
    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        // 用戶退出了
        // 相當于User類型的對象向session域當中刪除
        // 獲取application域對象
        ServletContext application = event.getSession().getServletContext();
        // 獲取域當中的數(shù)據(jù),肯定不是空
        Integer onlioncount = (Integer) application.getAttribute("onlioncount");
        onlioncount--;
        // 在存入域當中
        application.setAttribute("onlioncount",onlioncount);
    }
    // 定義屬性
    private String username;
    private String password;
    // 構造方法
    public User() {
    }
    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }
    // setter and getter
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

②修改UserServlet類和WelcomeServlet

// 把用戶名放進session
session.setAttribute("username",username);
// 改為這樣存
User user = new User(username, password);
session.setAttribute("user",user);

③修改過濾器LoginFilter

if("/index.jsp".equals(servletPath) || "/welcome".equals(servletPath) ||
                "/dept/login".equals(servletPath) || "/dept/exit".equals(servletPath)
                || (session != null && session.getAttribute("username") != null)){
// username改為user,因為前面存儲的名字變了
if("/index.jsp".equals(servletPath) || "/welcome".equals(servletPath) ||
                "/dept/login".equals(servletPath) || "/dept/exit".equals(servletPath)
                || (session != null && session.getAttribute("user") != null)){

④修改list.jsp頁面

<h3>歡迎${username}登錄</h3>
<!--修改為-->
<h3>歡迎${user.username}登錄,在線人數(shù)${onlioncount}人</h3>

⑤最終達到的效果

假如開了兩個瀏覽器,登錄了兩次

點擊退出登錄,刷新另一個瀏覽器的頁面

到此這篇關于Java Listener監(jiān)聽器使用規(guī)范詳細介紹的文章就介紹到這了,更多相關Java Listener監(jiān)聽器內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論

醴陵市| 阜新市| 庆城县| 合川市| 永靖县| 尼勒克县| 厦门市| 方山县| 察隅县| 利川市| 合肥市| 昌平区| 宜丰县| 冕宁县| 通辽市| 同江市| 成都市| 特克斯县| 梓潼县| 伊通| 泰和县| 夹江县| 会理县| 思茅市| 商丘市| 巴楚县| 行唐县| 娱乐| 泾川县| 巴林右旗| 太仓市| 当雄县| 来凤县| 农安县| 重庆市| 襄城县| 芜湖县| 甘洛县| 榆树市| 东平县| 潞城市|