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

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

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

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

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

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

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

④特殊的時刻如果想執(zhí)行這段代碼,你需要想到使用對應(yīng)的監(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)聽器的步驟

這里主要先講解熟悉的關(guān)于三個域?qū)ο蟮谋O(jiān)聽器:

ServletContext、ServletRequest、HttpSession

(1)以ServletContextListener為例

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

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

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

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

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

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

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

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

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

服務(wù)器關(guān)閉時,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 { // 服務(wù)器啟動時間點
    /**
     * 監(jiān)聽器中的方法不需要程序員手動調(diào)用。是發(fā)生某個特殊事件之后被服務(wù)器調(diào)用。
     * @param sce
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) { // 服務(wù)器關(guān)閉時間點
        // 現(xiàn)在這個特殊的時刻寫代碼,你寫就是了。它會被服務(wù)器自動調(diào)用。
        // 這個方法是在ServletContext對象被創(chuàng)建的時候調(diào)用。
        System.out.println("ServletContext對象創(chuàng)建了。");
    }
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // 現(xiàn)在這個特殊的時刻寫代碼,你寫就是了。它會被服務(wù)器自動調(diào)用。
        // 這個方法是在ServletContext對象被銷毀的時候調(diào)用。
        System.out.println("ServletContext對象被銷毀了。");
    }
}

(2)以ServletRequestListener為例

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

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

注:我們直接訪問http://localhost:8080/servlet15/會報404錯誤,因為默認(rèn)會訪問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時,默認(rèn)會創(chuàng)建session對象(九大內(nèi)置對象);先編寫一個my.jsp;在訪問my.jsp時,會創(chuàng)建session對象,調(diào)用 sessionCreated方法;

當(dāng)退出系統(tǒng)時,我們編寫銷毀session對象的方法,會調(diào)用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的使用

①我們知道對于域?qū)ο蠖加衧etAttribute、getAttribute、removeAttribute方法,分別可以向域中存數(shù)據(jù)、取數(shù)據(jù)、清除數(shù)據(jù);所以對于AttributeListener肯定是和這些處理域中數(shù)據(jù)有關(guān)。

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

③這里以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域當(dāng)中存儲數(shù)據(jù)的時候,以下方法被WEB服務(wù)器調(diào)用。
    @Override
    public void attributeAdded(HttpSessionBindingEvent se) {
        System.out.println("session data add");
    }
    // 將session域當(dāng)中存儲的數(shù)據(jù)刪除的時候,以下方法被WEB服務(wù)器調(diào)用。
    @Override
    public void attributeRemoved(HttpSessionBindingEvent se) {
        System.out.println("session data remove");
    }
    // session域當(dāng)中的某個數(shù)據(jù)被替換的時候,以下方法被WEB服務(wù)器調(diào)用。
    @Override
    public void attributeReplaced(HttpSessionBindingEvent se) {
        System.out.println("session data replace");
    }
}

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

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

注意:調(diào)用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)講解了關(guān)于域?qū)ο蟮谋O(jiān)聽器,九個監(jiān)聽器中就已經(jīng)學(xué)習(xí)了6個;接下來就先分析一下HttpSessionBindingListener;顧名思義就是關(guān)于數(shù)據(jù)綁定的!

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

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

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

對比當(dāng)數(shù)據(jù)放入放入域當(dāng)中,兩者會有什么區(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();
        // 準(zhǔn)備兩個對象: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注解進行標(biāo)注的(或者使用web.xml文件進行配置)

②該監(jiān)聽器監(jiān)聽的是session域中數(shù)據(jù)的變化。只要數(shù)據(jù)變化,則執(zhí)行相應(yīng)的方法;主要監(jiān)測點在session域?qū)ο笊稀?/p>

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

??HttpSessionBindingListener監(jiān)聽器

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

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

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

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

??總結(jié):

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

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

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

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

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

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

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

用戶登錄的標(biāo)志是什么?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)聽器中的唯一一個方法就會被調(diào)用。

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

①鈍化:session對象從內(nèi)存存儲到硬盤文件。

②活化:從硬盤文件把session恢復(fù)到內(nèi)存。

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

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

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

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

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

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

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

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

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

①編寫User類實現(xiàn)監(jiān)聽器的接口;然后修改關(guā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) {
        // 用戶登錄了
        // 相當(dāng)于User類型的對象向session域當(dāng)中存放
        // 獲取application域?qū)ο?
        // event.getSession()獲取到session;在調(diào)用getServletContext()獲取到域?qū)ο?
        ServletContext application = event.getSession().getServletContext();
        // 獲取到在線人數(shù)
        Object onlioncount = application.getAttribute("onlioncount");
        // 第一個用戶登錄,里面什么都沒有,返回的是一個null
        if (onlioncount == null) {
            application.setAttribute("onlioncount",1);
        }else {
            // 直接 onlioncount++有問題,前面是Object類型,強轉(zhuǎn)
            Integer count = (Integer)onlioncount;
            count++;
            // 在存入域當(dāng)中
            application.setAttribute("onlioncount",count);
        }
    }
    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        // 用戶退出了
        // 相當(dāng)于User類型的對象向session域當(dāng)中刪除
        // 獲取application域?qū)ο?
        ServletContext application = event.getSession().getServletContext();
        // 獲取域當(dāng)中的數(shù)據(jù),肯定不是空
        Integer onlioncount = (Integer) application.getAttribute("onlioncount");
        onlioncount--;
        // 在存入域當(dāng)中
        application.setAttribute("onlioncount",onlioncount);
    }
    // 定義屬性
    private String username;
    private String password;
    // 構(gòu)造方法
    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>

⑤最終達(dá)到的效果

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

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

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

相關(guān)文章

最新評論

城固县| 潮安县| 木里| 高青县| 罗平县| 乌拉特后旗| 遵义县| 永州市| 内丘县| 马关县| 迭部县| 宾阳县| 永和县| 镇康县| 全州县| 逊克县| 卢氏县| 乐业县| 高尔夫| 丰都县| 东兴市| 林西县| 紫阳县| 九龙坡区| 延津县| 无棣县| 黄梅县| 广水市| 深水埗区| 达孜县| 丰台区| 常山县| 潼南县| 温泉县| 信宜市| 安吉县| 峨边| 海门市| 蓬莱市| 广东省| 博客|