首页 > 编程语言 >老杜 JavaWeb 讲解(二十) ——Listener监听器

老杜 JavaWeb 讲解(二十) ——Listener监听器

时间:2023-08-09 16:23:39浏览次数:40  
标签:username JavaWeb Listener session user 监听器 public User

(十八)Listener监听器

引子:静态代码块

package com.zwm.javaweb.servlet;

/**
 * @author 猪无名
 * @date 2023/8/8 13 47
 * discription:
 */
public class test2 {
    // 静态代码块在类加载时执行,并且只执行一次。
    //这个语法很简单,但什么时候用?很疑惑

    //假如,你希望在类加载的时候运行一段代码,这时候就可以用到静态代码块,这是Java语言预留给程序员的一个时机(类加载时机)。
    //静态代码块实际上用的不多。
    static {
        System.out.println("类加载了。");
    }

    public static void main(String[] args) {

    }
}

监听器的作用就类似静态代码块,是预留给程序员的时机。

  • 什么是监听器?

    • 监听器是Servlet规范中的一员。就像Filter一样。Filter也是Servlet规范中的一员。
    • 在Servlet中,所有的监听器接口都是以“Listener”结尾。
  • 监听器有什么用?

    • 监听器实际上是Servlet规范留给我们javaweb程序员的特殊时机。
    • 特殊的时刻如果想执行这段代码,你需要想到使用对应的监听器。
  • Servlet规范中提供了哪些监听器?

    • jakarta.servlet包下:
      • ServletContextListener
      • ServletContextAttributeListener
      • ServletRequestListener
      • ServletRequestAttributeListener
    • jakarta.servlet.http包下:
      • HttpSessionListener
      • HttpSessionAttributeListener
        • 该监听器需要使用@WebListener注解进行标注。
        • 该监听器监听的是什么?是session域中数据的变化。只要数据变化,则执行相应的方法。主要监测点在session域对象上。
      • HttpSessionBindingListener
        • 该监听器不需要使用@WebListener进行标注。
        • 假设User类实现了该监听器,那么User对象在被放入session的时候触发bind事件,User对象从session中删除的时候,触发unbind事件。
        • 假设Customer类没有实现该监听器,那么Customer对象放入session或者从session删除的时候,不会触发bind和unbind事件。
      • HttpSessionIdListener
        • session的id发生改变的时候,监听器中的唯一一个方法就会被调用。
      • HttpSessionActivationListener
        • 监听session对象的钝化和活化的。
        • 钝化:session对象从内存存储到硬盘文件。
        • 活化:从硬盘文件把session恢复到内存。
  • 实现一个监听器的步骤:以ServletContextListener为例。

    • 第一步:编写一个类实现ServletContextListener接口。并且实现里面的方法。

      • public class Listener01 implements ServletContextListener {
            @Override
            public void contextInitialized(ServletContextEvent sce) {
                //这个方法是在ServletContext对象被创建的时候调用的。
                Sustem.out.println("ServletContext对象被创建的时候调用的。");
            }
        
            @Override
            public void contextDestroyed(ServletContextEvent sce) {
        		//这个方法是在ServletContext对象被销毁的时候调用的。
                 Sustem.out.println("ServletContext对象被销毁的时候调用的。");
            }
        }
        
    • 第二步:在web.xml文件中对ServletContextListener进行配置,如下:

      • <listener>
            <listener-class>com.zwm.javaweb.listener.Listener01</listener-class>
        </listener>
        
      • 当然,第二步也可以不使用配置文件,也可以用注解,例如:@WebListener

  • 注意:所有监听器中的方法都是不需要javaweb程序员手动调用的,由服务器来负责调用?什么时候被调用呢?

    • 当某个特殊的事件发生(特殊的事件发生其实就是某个时机到了。)之后,被web服务器自动调用。
  • 思考一个业务场景:

    • 请编写一个功能,记录该网站实时的在线用户的个数。
    • 我们可以通过服务器端有没有分配session对象,因为一个session代表了一个用户。有一个session就代表有一个用户。如果你采用这种逻辑去实现的话,session有多少个,在线用户就有多少个。这种方式的话:HttpSessionListener够用了。session对象只要新建,则count++,然后将count存储到ServletContext域当中,在页面展示在线人数即可。
    • 业务发生改变了,只统计登录的用户的在线数量,这个该怎么办?
      • session.setAttribute("user", userObj);
      • 用户登录的标志是什么?session中曾经存储过User类型的对象。那么这个时候可以让User类型的对象实现HttpSessionBindingListener监听器,只要User类型对象存储到session域中,则count++,然后将count++存储到ServletContext对象中。页面展示在线人数即可。

改造oa项目:显示当前在线的人数:

  • 什么代表着用户登录了?
    • session.setAttribute("user", userObj); User类型的对象只要往session中存储过,表示有新用户登录。
  • 什么代表着用户退出了?
    • session.removeAttribute("user"); User类型的对象从session域中移除了。
    • 或者有可能是session销毁了。(session超时)

第一步:添加一个User类实现HttpSessionBindingListener接口:

package com.zwm.oa.bean;

import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpSessionBindingEvent;
import jakarta.servlet.http.HttpSessionBindingListener;

import java.util.Objects;

/**
 * @author 猪无名
 * @date 2023/8/9 15 17
 * discription:
 */
public class User implements HttpSessionBindingListener {
    private String username;
    private String password;


    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        //用户登录了(User类型的对象向session中存放了。)
        ServletContext application = event.getSession().getServletContext();

        Object onlinecount = application.getAttribute("onlinecount");
        if(onlinecount == null){
            application.setAttribute("onlinecount",1);
        }else {
            int count = (Integer)onlinecount;
            count++;
            application.setAttribute("onlinecount",count);
        }
    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        //用户退出了(User类型的对象从session中删除了。)
        ServletContext application = event.getSession().getServletContext();
        Integer onlinecount = (Integer)application.getAttribute("onlinecount");
        onlinecount--;
        application.setAttribute("onlinecount",onlinecount);

    }

    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    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;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(username, user.username) && Objects.equals(password, user.password);
    }

    @Override
    public int hashCode() {
        return Objects.hash(username, password);
    }
}

第二步:更改原来的代码

在原来的登录和退出相关的代码处进行修改,主要有三处:

1:UserServlet类中的doExit方法,在消除session对象时,消除添加到session域中的user对象,实现了HttpSessionBindingListener接口的user对象会在被清除的时候,调用valueUnbound方法,从而实现application域中的数值减一。

 HttpSession session = request.getSession();
        if(session !=null){
            //从session域中删除user对象
            session.removeAttribute("user");

            //手动销毁session
            session.invalidate();
        }

2:UserServlet类中的doLogin方法,当登录验证成功之后,向session域中添加user对象。在添加的时候,user对象会调用valueBound方法,实现application域中的数值加一。

User user = new User(username,password);
session.setAttribute("user",user);

3:项目设置了默认的访问首页/welcome,它是用来实现cookie十天免登录的。假如在本地存储的有cookie对象,在判断信息无误后,也要跳转到项目首页,这时候也是需要增加在线人数的。

User user = new User(username,password);
session.setAttribute("user",user);

第三步:更改jsp代码,显示在线人数

<h2>欢迎${username},在线人数${onlinecount}</h2>
<%--这里的username也可以通过${user.username}获取。--%>



到此为止,老杜JavaWeb部分结束。




标签:username,JavaWeb,Listener,session,user,监听器,public,User
From: https://www.cnblogs.com/LJY-YSWZ/p/17617127.html

相关文章

  • JavaWeb短信验证的实现方法
    JavaWeb短信验证的实现方法短信验证是现代应用程序中常用的一种用户身份验证方式。在JavaWeb开发中,我们可以通过一些简单而有效的方法实现短信验证功能。本文将介绍如何使用Java编程语言来实现JavaWeb短信验证。JavaWeb短信验证的实现方法首先,我们需要一个短信服务提供商,比如阿......
  • JavaWebSocket心跳机制详解
    JavaWebSocket心跳机制详解WebSocket是一种在Web浏览器和服务器之间进行全双工通信的协议,它提供了一种简单而强大的方式来实现实时数据传输。在使用WebSocket时,心跳机制是非常关键的,它能够保持连接的稳定性并及时发现连接的异常。本文将详细解释JavaWebSocket心跳机制的实现原理......
  • 老杜 JavaWeb 讲解(十九) ——Filter过滤器
    (十七)Filter过滤器Filter过滤器当前的OA项目存在什么缺陷?DeptServlet、EmpServlet、OrderServlet。每一个Servlet都是处理自己相关的业务。在这些Servlet执行之前都是需要判断用户是否登录了。如果用户登录了,可以继续操作,如果没有登录,需要用户登录。这段判断用户是否登录......
  • JavaWeb之Servlet入门版教务系统(二)
    本次要分享的内容是之前教务系统中系统管理模块下的角色列表功能,包括对角色信息进行增删改查以及对当前的用户进行角色的分配(重点讲解)。首先还是需要使用mysql数据库准备一张角色表,建表语句如下:DROPTABLEIFEXISTS`sys_role`;CREATETABLE`sys_role`(`role_id`int(11)NO......
  • 老杜 JavaWeb 讲解(十八) ——项目优化(Servlet+JSP+EL+JSTL)
    (十六)项目优化(Servlet+JSP+EL+JSTL)相关视频:55-EL表达式JSTL和base标签改造OA新旧代码对比:注意点:Java代码不需要改动,只需要更改jsp代码。将需要的包导入:jakarta.servlet.jsp.jstl-2.0.0.jarjakarta.servlet.jsp.jstl-api-2.0.0.jarmysql-connector-j-8.0.31.j......
  • 老杜 JavaWeb 讲解(十七) ——JSP补充
    (十六)JSP补充相关视频:49-JSP的page指令以及九大内置对象和EL表达式指令指令的作用:指导JSP的翻译引擎如何工作(指导当前的JSP翻译引擎如何翻译JSP文件。)指令包括哪些呢?include指令:包含指令,在JSP中完成静态包含,很少用了。(这里不讲)taglib指令:引入标签库的指令。这个到JS......
  • 《http篇》通过HttpListener实现http服务
    简单http服务如果想实现更高级http服务,可以看下述目录参考链接:https://blog.csdn.net/qq_36702996/article/details/78892380HttpListener提供一个简单的、可通过编程方式控制的HTTP协议侦听器。通过它可以很容易的提供一些Http服务,而无需启动IIS这类大型服务程序。注意:该类......
  • JavaWeb和MVC三层架构
    JavaWeb概述网站发布和部署一定要依托技术语言吗:不一定,一个网站可以直接发布和部署,因为因为浏览器能够识别网页只需要两样东西,网络和静态页面,还有一个装在他们的容器,比如nginx。静态页面面临的问题:1:静态网页是固定的,是不可变的。如果一个网站比如腾讯首页,这里需要1000文......
  • JavaWeb之Servlet入门版教务系统(一)
    本次要分享的内容是使用Servlet技术实现最简单的从页面到后台的一个简化版的教务系统功能模块。在讲述系统之前,首先需要了解一下JavaWeb中的MVC分层重要思想,请看下图:MVC分层思想把软件系统分为View(视图层),Controller(控制层),Model(模型层),通过这三层结构。让页面请求必须通过控制......
  • [Javascript] removeEventListener
    Mistake1:Notusingthesamefunctionreference//Wrongbutton.addEventListener('click',()=>{console.log('click')})button.removeEventListener('click',()=>{console.log('click')})//Won'tremovet......