Java监听器的理解与实现

news2024/12/25 1:32:27

文章目录

  • 初识监听器
  • Listener接口分类
    • ServletContext监听器
    • HttpSession监听器
    • ServletRequest监听器
  • Java代码实现
    • ServletContextListener
    • ServletContextAttributeListener
    • HttpSessionListener
    • HttpSessionAttributeListener
    • HttpSessionActivationListener
    • HttpSessionBindingListener
    • ServletRequestListener
    • ServletRequestAttributeListener
  • 模仿监听器Demo

初识监听器

== 什么是监听器==
监听器也叫Listener,是Servlet的监听器,它可以监听客户端的请求、服务端的操作等。通过监听器,可以自动激发一些操作,比如监听在线的用户的数量。

监听器,字面上的理解就是监听观察某个事件(程序)的发生情况,当被监听的事件真的发生了的时候,事件发生者(事件源) 就会给注册该事件的监听者(监听器)发送消息,告诉监听者某些信息,同时监听者也可以获得一份事件对象,根据这个对象可以获得相关属性和执行相关操作。

监听器模型涉及以下三个对象,模型图如下:

  • (1)事件:用户对组件的一个操作,或者说程序执行某个方法,称之为一个事件,如机器人程序执行工作。
  • (2)事件源:发生事件的组件就是事件源,也就是被监听的对象,如机器人可以工作,可以跳舞,那么就可以把机器人看做是一个事件源。
  • (3)事件监听器(处理器):监听并负责处理事件的方法,如监听机器人工作情况,在机器人工作前后做出相应的动作,或者获取机器人的状态信息。
    在这里插入图片描述
    执行顺序如下:
    1、给事件源注册监听器。
    2、组件接受外部作用,也就是事件被触发。
    3、组件产生一个相应的事件对象,并把此对象传递给与之关联的事件处理器。
    4、事件处理器启动,并执行相关的代码来处理该事件。

java监听器监听的内容是什么?监听器作用在哪个事件上?是在哪配置的监听内容的?

首先,监听器要怎么实现?
Java事件由事件类监听接口组成,自定义一个事件前,必须提供一个事件的监听接口以及一个事件类。JAVA中监听接口是继承java.util.EventListener的类,事件类继承java.util.EventObject的类。很多基本的事件系统已经为我们定义好了,我们只要学会调用即可,但是为了更加灵活地满足特定的需求,我们有时候也需要自定义事件。

监听器的实质是什么?
一个类实现某个监听器接口,然后实现接口对应的方法,达到监听具体事项的动作。

Listener接口分类

监听器的接口有哪些?

监听器接口分三类:ServletContext,HttpSession,ServletRequest。

ServletContext监听器

ServletContext

  • ServletContextListener 监听ServletContext对象
  • ServletContextAttributeListener 监听对ServletContext属性的操作,比如说增加,删除,修改

HttpSession监听器

HttpSession

  • HttpSessionListener 监听Session对象
  • HttpSessionAttributeListener 监听Session的属性操作
  • HttpSessionActivationListener 监听HTTP会话的active和passivate情况,passivate是指非活动的session被写入持久设备(如硬盘),active相反。
  • HttpSessionBindingListener 监听器感知Session绑定的事件监听器

注意:Servlet 规范中定义了两个特殊的监听器接口"HttpSessionBindingListenerHttpSessionActivationListener"来帮助JavaBean
对象了解自己在Session域中的这些状态: ,实现这两个接口的类不需要 web.xml 文件中进行注册。


HttpSessionActivationListener 监听

实现了HttpSessionActivationListener接口的 JavaBean 对象可以感知自己被活化和钝化的事件

活化:javabean对象和Session一起被反序列化(活化)到内存中(硬盘到内存);
钝化:javabean对象和Session一起序列化到硬盘中(内存到硬盘);
javabean对象存在Session中,当服务器把session序列化到硬盘上时,如果Session中的javabean对象实现了Serializable接口
那么服务器会把session中的javabean对象一起序列化到硬盘上,javabean对象和Session一起被序列化到硬盘中的这个操作称之为钝化
如果Session中的javabean对象没有实现Serializable接口,那么服务器会先把Session中没有实现Serializable接口的javabean对象移除
然后再把Session序列化(钝化)到硬盘中;

当绑定到 HttpSession对象中的javabean对象将要随 HttpSession对象被钝化之前,
web服务器调用该javabean对象的 sessionWillPassivate方法,
这样javabean对象就可以知道自己将要和 HttpSession对象一起被序列化(钝化)到硬盘中
当绑定到HttpSession对象中的javabean对象将要随 HttpSession对象被活化之后,
web服务器调用该javabean对象的sessionDidActive方法,
这样javabean对象就可以知道自己将要和 HttpSession对象一起被反序列化(活化)回到内存中 

HttpSessionBindingListener 监听

保存在Session域中的对象可以有多种状态:
(1)绑定(session.setAttribute("bean",Object))Session中;
(2)从Session域中解除(session.removeAttribute("bean"))绑定;
(3)随Session对象持久化到一个存储设备中;
(4)随Session对象从一个存储设备中恢复;

Servlet 规范中定义了两个特殊的监听器接口"HttpSessionBindingListener和HttpSessionActivationListener"来帮助JavaBean 对象了解自己在Session域中的这些状态: ,实现这两个接口的类不需要 web.xml 文件中进行注册。

ServletRequest监听器

ServletRequest

  • ServletRequestListener监听Requst对象
  • ServletRequestAttributeListener监听Request中的属性操作。

怎么知道我到底要实现哪个监听器?
看需求,看要监听的东西是什么,比如说监听上下文的有:ServletContextListener,ServletContextAttributeListener
监听request的有:ServletRequestListener,ServletRequestAttributeListener

监听器是怎样被调用的?为什么直接在web.xml里面配置一个listerner,程序就会自动去监听?
因为监听器是需要实现监听器接口的,接口的底层应该是封装好了怎样去监听的逻辑的,所以说直接实现监听器接口,程序启动后就能直接去监听。

Java代码实现

ServletContextListener

监听器类代码

package cn.itcast.erp.listener.request;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;

public class ServletRequestListener1 implements ServletRequestListener {

    /**
     * 该请求即将超出Web应用程序的范围。
     * request将要销毁
     */
    @Override
    public void requestDestroyed(ServletRequestEvent event) {
        System.out.println("request将要销毁");
    }

    /**
     * 该请求即将进入Web应用程序的范围。
     * request初始化
     */
    @Override
    public void requestInitialized(ServletRequestEvent event) {
        System.out.println("request初始化");
    }

}

web.xml配置代码

    <!-- ServletContext对象监听器 -->
    <listener>
        <listener-class>cn.itcast.erp.listener.servletContext.ServletContextListener1</listener-class>
    </listener>

ServletContextAttributeListener

监听器类代码:

package cn.itcast.erp.listener.request;

import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;

public class ServletRequestAttributeListener1 implements ServletRequestAttributeListener {

    /**
     * 通知一个新的属性被添加到servlet请求。 在添加属性后调用。
     */
    @Override
    public void attributeAdded(ServletRequestAttributeEvent event) {
        System.out.println("request添加属性后调用");
    }

    /**
     * 通知现有的属性已经从servlet请求中删除。 在属性被删除后调用。
     */
    @Override
    public void attributeRemoved(ServletRequestAttributeEvent event) {
        System.out.println("request删除属性后调用");
    }

    /**
     * 通知servlet请求中已经替换了一个属性。 在属性被替换后调用。
     */
    @Override
    public void attributeReplaced(ServletRequestAttributeEvent event) {
        System.out.println("request替换属性后调用");
        String name = event.getName();
        Object value = event.getValue();
        System.out.println("request被替换的key:" + name + "  ,替换前的value:" + value);
    }

}

web.xml配置代码:

    <!-- ServletContext属性的操作监听器  -->
    <listener>
        <listener-class>cn.itcast.erp.listener.servletContext.ServletContextAttributeListener1</listener-class>
    </listener>

HttpSessionListener

监听器类代码:

package cn.itcast.erp.listener.session;

import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class HttpSessionListener1 implements HttpSessionListener{
    /**
     * 通知会话已创建。
     * session创建之后调用
     */
    @Override
    public void sessionCreated(HttpSessionEvent event) {
        System.out.println("session创建之后");
        HttpSession session = event.getSession();
    }

    /**
     * 通知会话即将失效。
     * session销毁之前调用
     */
    @Override
    public void sessionDestroyed(HttpSessionEvent event) {
        System.out.println("session销毁之前");
        HttpSession session = event.getSession();
    }

}

web.xml配置代码:

    <!-- HttpSession对象监听器 -->
    <listener>
        <listener-class>cn.itcast.erp.listener.session.HttpSessionListener1</listener-class>
    </listener>

HttpSessionAttributeListener

package cn.itcast.erp.listener.session;

import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;

public class HttpSessionAttributeListener1 implements HttpSessionAttributeListener{

    /**
     * 通知某个属性已被添加到会话中。 在添加属性后调用。
     */
    @Override
    public void attributeAdded(HttpSessionBindingEvent event) {
        System.out.println("session添加属性后调用");
        HttpSession session = event.getSession();
        String name = event.getName();
        Object value = event.getValue();
        System.out.println("被添加到session中的属性:" + "key=" + name + "   ,value=" + value);
    }

    /**
     * 通知某个属性已从会话中删除。 在属性被删除后调用。
     */
    @Override
    public void attributeRemoved(HttpSessionBindingEvent event) {
        System.out.println("session删除属性后调用");
        HttpSession session = event.getSession();
        String name = event.getName();
        Object value = event.getValue();
        System.out.println("被删除的session中的属性:" + "key=" + name + "   ,value=" + value);
    }

    /**
     * 在会话中通知属性已被替换。 在属性被替换后调用。
     */
    @Override
    public void attributeReplaced(HttpSessionBindingEvent event) {
        System.out.println("session替换属性后调用");
        HttpSession session = event.getSession();
        String name = event.getName();
        Object value = event.getValue();
        System.out.println("被替换的session中的属性:" + "key=" + name + "   ,替换之前的value=" + value);
    }

}

web.xml配置代码:

    <!-- HttpSession属性的操作监听器 -->
    <listener>
        <listener-class>cn.itcast.erp.listener.session.HttpSessionAttributeListener1</listener-class>
    </listener>

HttpSessionActivationListener

监听器类代码(不需要配置web.xml):

package cn.itcast.erp.listener.session;

import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;


public class HttpSessionActivationListener1 implements HttpSessionActivationListener {

    /**
     * 通知该会话即将被钝化。
     * 当前javaBean绑定到session中钝化之前
     */
    @Override
    public void sessionWillPassivate(HttpSessionEvent event) {
        System.out.println("session钝化之前");
        HttpSession session = event.getSession();
    }

    /**
     * 通知该会话刚刚被激活。
     * 当前javaBean绑定到session中活化之后
     */
    @Override
    public void sessionDidActivate(HttpSessionEvent event) {
        System.out.println("session活化之后");
        HttpSession session = event.getSession();
    }

}

配置Session对象的管理org.apache.catalina.session.PersistentManager方便序列化测试:
添加配置文件webapp/META-INF/context.xml
在这里插入图片描述
内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <!-- Session对象的管理 -->
    <!-- maxIdleSwap="1" ():n秒之后就将HttpSession对象钝化到本地硬盘的一个文件夹中 -->
    <Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="true" maxIdleSwap="1">
        <Store className="org.apache.catalina.session.FileStore" directory="e:/session/"></Store>
    </Manager>
</Context>

测试代码:jsp页面

<%@page import="cn.itcast.erp.listener.session.HttpSessionBindingListener1"%>
<%@page import="cn.itcast.erp.listener.session.HttpSessionActivationListener1"%>
<%@page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>测试HttpSessionActivationListener监听(session的活化和钝化)</title>
  </head>

  <body>
    <% 
        //测试session活化和钝化监听器HttpSessionActivationListener
        session.setAttribute("sessionActivation",new HttpSessionActivationListener1());

        //测试session绑定和解绑监听器
        session.setAttribute("sessionBind", new HttpSessionBindingListener1());
        session.removeAttribute("sessionBind");

    %>
    <h1>session活化和钝化监听</h1>
  </body>
</html>

HttpSessionBindingListener

监听器类代码(不需要配置web.xml):

package cn.itcast.erp.listener.session;

import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;

public class HttpSessionBindingListener1 implements HttpSessionBindingListener {

    /**
     * 通知对象它正在被绑定到会话并标识会话。(还未绑定)
     */
    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        System.out.println("当前对象正在绑定到session中,还未绑定");
        HttpSession session = event.getSession();

        String name = event.getName();
        Object value = event.getValue();
        System.out.println("将要被绑定到session中的key值:" + name + "value值:" + value);
        System.out.println("value值是否是当前对象:" + (value == this));//true

        Object valueNow = session.getAttribute(name);
        System.out.println("valueNow:" + valueNow);//null,还未绑定


    }

    /**
     * 通知对象它正在从会话中解除绑定并标识会话。(还未解除绑定)
     */
    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        System.out.println("当前对象它正在从会话中解除绑定");
        HttpSession session = event.getSession();

        String name = event.getName();
        Object value = event.getValue();
        System.out.println("将要解除绑定session中的key值:" + name + "value值:" + value);
        System.out.println("value值是否是当前对象:" + (value == this));//true

        Object valueNow = session.getAttribute(name);
        System.out.println("valueNow:" + valueNow);//null,还未解除绑定
    }

}

测试代码:jsp页面

<%@page import="cn.itcast.erp.listener.session.HttpSessionBindingListener1"%>
<%@page import="cn.itcast.erp.listener.session.HttpSessionActivationListener1"%>
<%@page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>测试HttpSessionActivationListener监听(session的活化和钝化)</title>
  </head>

  <body>
    <% 
        //测试session活化和钝化监听器HttpSessionActivationListener
        session.setAttribute("sessionActivation",new HttpSessionActivationListener1());

        //测试session绑定和解绑监听器
        session.setAttribute("sessionBind", new HttpSessionBindingListener1());
        session.removeAttribute("sessionBind");

    %>
    <h1>session活化和钝化监听</h1>
  </body>
</html>

ServletRequestListener

监听器类代码:

package cn.itcast.erp.listener.request;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;

public class ServletRequestListener1 implements ServletRequestListener {

    /**
     * 该请求即将超出Web应用程序的范围。
     * request将要销毁
     */
    @Override
    public void requestDestroyed(ServletRequestEvent event) {
        System.out.println("request将要销毁");
    }

    /**
     * 该请求即将进入Web应用程序的范围。
     * request初始化
     */
    @Override
    public void requestInitialized(ServletRequestEvent event) {
        System.out.println("request初始化");
    }

}

web.xml配置代码:

    <!-- ServletRequest对象监听器 -->
    <listener>
        <listener-class>cn.itcast.erp.listener.request.ServletRequestListener1</listener-class>
    </listener>

ServletRequestAttributeListener

监听器类代码:

package cn.itcast.erp.listener.request;

import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;


public class ServletRequestAttributeListener1 implements ServletRequestAttributeListener {

    /**
     * 通知一个新的属性被添加到servlet请求。 在添加属性后调用。
     */
    @Override
    public void attributeAdded(ServletRequestAttributeEvent event) {
        System.out.println("request添加属性后调用");
    }

    /**
     * 通知现有的属性已经从servlet请求中删除。 在属性被删除后调用。
     */
    @Override
    public void attributeRemoved(ServletRequestAttributeEvent event) {
        System.out.println("request删除属性后调用");
    }

    /**
     * 通知servlet请求中已经替换了一个属性。 在属性被替换后调用。
     */
    @Override
    public void attributeReplaced(ServletRequestAttributeEvent event) {
        System.out.println("request替换属性后调用");
        String name = event.getName();
        Object value = event.getValue();
        System.out.println("request被替换的key:" + name + "  ,替换前的value:" + value);
    }

}

web.xml配置代码:

    <!-- ServletRequest属性的操作监听器  -->
    <listener>
        <listener-class>cn.itcast.erp.listener.request.ServletRequestAttributeListener1</listener-class>
    </listener>

模仿监听器Demo

需求:实现机器人工作和跳舞,在机器人开始工作和跳舞之前输出相关提示。

首先创建一个事件源Robot:

package com.ssm.listener.robotListener;

/**
 * 事件源:机器人
 */
public class Robot {

    private RobotListener listener;

    /**
     * 注册机器人监听器
     * @param listener
     */
    public void registerListener(RobotListener listener){
     this.listener  = listener;
    }

    /**
     * 工作
     */
    public void working(){
        if(listener!=null){
            Even even = new Even(this);
            this.listener.working(even);
        }
        System.out.println("机器人开始工作......");
    }

    /**
     * 跳舞
     */
    public void dancing(){
        if(listener!=null){
            Even even = new Even(this);
            this.listener.dancing(even);
        }
        System.out.println("机器人开始跳舞......");
    }


}

创建时间对象Even:

package com.ssm.listener.robotListener;

/**
 * 事件对象
 */
public class Even {

    private Robot robot;

    public Even(){
        super();
    }
    public Even(Robot robot){
        super();
        this.robot = robot;
    }


    public Robot getRobot() {
        return robot;
    }

    public void setRobot(Robot robot) {
        this.robot = robot;
    }
}

创建时间监听器接口RobotListener:

package com.ssm.listener.robotListener;

/**
 * 事件监听器
 */
public interface RobotListener {

    public void working(Even even);
    public void dancing(Even even);
}

实现事件监听器MyRobotListener:

package com.ssm.listener.robotListener;

public class MyRobotListener implements  RobotListener{
    @Override
    public void working(Even even) {
        Robot robot = even.getRobot();
        System.out.println("机器人工作提示:请看管好的你机器人,防止它偷懒!");
    }

    @Override
    public void dancing(Even even) {
        Robot robot = even.getRobot();
        System.out.println("机器人跳舞提示:机器人跳舞动作优美,请不要走神哦!");
    }
}

事件监听器测试类

TestListener:

package com.ssm.listener.robotListener;

public class TestListener {

    public static void main(String[] args) {
        Robot robot = new Robot();
        robot.registerListener(new MyRobotListener());
        robot.working();
        robot.dancing();
    }
}

输出结果:
在这里插入图片描述

参考文章(侵删):
https://blog.csdn.net/menghuanzhiming/article/details/79042182
https://www.cnblogs.com/againn/p/9512013.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/360710.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在 4G 内存的机器上,申请 8G 内存会怎么样?

在 4GB 物理内存的机器上&#xff0c;申请 8G 内存会怎么样&#xff1f; 这个问题在没有前置条件下&#xff0c;就说出答案就是耍流氓。这个问题要考虑三个前置条件&#xff1a; 操作系统是 32 位的&#xff0c;还是 64 位的&#xff1f;申请完 8G 内存后会不会被使用&#x…

【机器学习】集成学习

1.什么是集成学习 集成学习的基本思想是结合多个学习器组合成一个性能更好的学习器。这类方法会训练多个弱学习器&#xff08;基学习器&#xff09;并将它们输出的结果以某种策略结合起来组成一个强学习器。 2.集成学习的几种方法 根据个体学习器的生成方式&#xff0c;集成学…

手把手教你用React Hook和TypeScript从零实现虚拟滚动列表组件

前言 k8s 全称 kubernetes&#xff0c;这个名字大家应该都不陌生&#xff0c;k8s是为容器服务而生的一个可移植容器的编排管理工具&#xff0c;集应用的部署和运维&#xff0c;负载均衡&#xff0c;服务发现和扩容&#xff0c;版本回滚于一身&#xff0c;越来越多的公司正在拥…

linux集群技术(二)--keepalived(高可用集群)(二)

案例1--keepalived案例2--keepalived Lvs集群1.案例1--keepalived 1.1 环境 初识keepalived&#xff0c;实现web服务器的高可用集群。 Server1: 192.168.26.144 Server2: 192.168.26.169 VIP: 192.168.26.190 1.2 server1 创建etc下的…

02-04 周六 图解机器学习 SVM 支持向量机分类学习

02-04 周六 图解机器学习 SVM 支持向量机分类学习时间版本修改人描述2023年2月4日11:15:16V0.1宋全恒新建文档 环境搭建 首先搭建jupyter环境&#xff0c;方便可视化 (base) rootnode33-a100:~# docker run --name sqh-learn -d -p 10088:8888 -it 10.101.12.128/framework/ju…

Qt-QProcess-启动子进程-控制台进程隐藏-获取子进程标准输出和返回码

文章目录1.隐藏控制台程序1.1.控制台程序生成即隐藏1.2.调用程序隐藏控制台2.QProcess2.1.基础用法-start和startDetached2.2.获取子进程的标准输出3.代码范例3.1.等待进程执行完毕&#xff0c;获取所有的输出3.2.子进程返回信号3.3.进程是否启动3.4.执行命令行3.5.与子进程交互…

GIT客户端安装

步骤1&#xff1a;运行“Git-2.13.1-64-bit.exe”&#xff0c;并点击“运行”按钮&#xff08;默认&#xff09;步骤2&#xff1a;许可信息页面&#xff0c;点击“Next”&#xff08;默认&#xff09;步骤3&#xff1a;选择安装路径&#xff08;默认&#xff09;步骤4&#xff…

记一次 .NET 某医保平台 CPU 爆高分析

一&#xff1a;背景 1. 讲故事 一直在追这个系列的朋友应该能感受到&#xff0c;我给这个行业中无数的陌生人分析过各种dump&#xff0c;终于在上周有位老同学找到我&#xff0c;还是个大妹子&#xff0c;必须有求必应 &#x1f601;&#x1f601;&#x1f601;。 妹子公司的…

IDEA高效插件和设置

安装好Intellij idea之后&#xff0c;进行如下的初始化操作&#xff0c;工作效率提升十倍。 一. 安装插件 1. Codota 代码智能提示插件 只要打出首字母就能联想出一整条语句&#xff0c;这也太智能了&#xff0c;还显示了每条语句使用频率。 原因是它学习了我的项目代码&…

力扣-从不订购的客户

大家好&#xff0c;我是空空star&#xff0c;本篇带大家了解一道简单的力扣sql练习题。 文章目录前言一、题目&#xff1a;183. 从不订购的客户二、解题1.正确示范①提交SQL运行结果2.正确示范②提交SQL运行结果3.正确示范③提交SQL运行结果4.正确示范④提交SQL运行结果总结前言…

2月编程语言排行榜谁还没有看?

近日&#xff0c;TIOBE公布了2023年2月编程语言排行榜&#xff0c;本月各个语言表现如何&#xff1f;谁又摘得桂冠&#xff1f;一起来看看吧&#xff01; TIOBE 2月Top15编程语言&#xff1a; 详细榜单查看TIOBE官网 https://www.tiobe.com/tiobe-index/ 关注IT行业的小伙伴们…

Qt音视频开发15-动态切换解码内核的设计

一、前言 动态切换解码内核这个需求也是源自客户的真实需求&#xff0c;既然是动态切换&#xff0c;那肯定是运行期间切换&#xff0c;而不是通过改变标志位重新编译程序来切换&#xff0c;最开始做的就是这种方式&#xff0c;这样就是实现起来简单&#xff0c;但是用起来不够…

OpenGL ES基础简介

简介 视频的渲染源是 YUV 或者 RGBA 格式的数据&#xff0c;这种数据是描述画面最基础的格式&#xff0c;其中 YUV 常用在视频的原始格式中&#xff0c;RGBA 常用在一些图像的原始格式上。 目前各个平台最终渲染到屏幕上的都是 RGBA 格式的&#xff0c;因为硬件对屏幕上的设计…

【可视化实战】Python 绘制出来的数据大屏真的太惊艳了

今天我们在进行一个Python数据可视化的实战练习&#xff0c;用到的模块叫做Panel&#xff0c;我们通过调用此模块来绘制动态可交互的图表以及数据大屏的制作。 而本地需要用到的数据集&#xff0c;可在kaggle上面获取 https://www.kaggle.com/datasets/rtatman/188-million-us…

SpringBoot之DEBUG远程调试黑科技?

所谓的远程调试就是服务端程序运行在一台远程服务器上&#xff0c;我们可以在本地服务端的代码&#xff08;前提是本地 的代码必须和远程服务器运行的代码一致&#xff09;中设置断点&#xff0c;每当有请求到远程服务器时时能够在本地知道 远程服务端的此时的内部状态。 简单的…

计算机408考研先导课---C语言难点

以下为小编在重温C语言时&#xff0c;容易犯错的一些点&#xff0c;希望列出来对大家有一定帮助&#xff01; 一、整型变量数的范围 类型说明符长度&#xff08;字节&#xff09;数的范围int4/2&#xff08;有些为4字节&#xff0c;有些为2字节&#xff09;-32768~32767short2…

ArcMap出图小技巧:主图设计、图例、比例尺、指北针、标题

ArcMap一个重要的功能是出图&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 因为图片对于一些文字描述来说更为直观&#xff0c;所以掌握一些出图技巧也是极为重要的&#xff0c;不仅能让我们在数据处理过程快速得到我们想要的图层&#xff0c;也可以让图层看起…

Teradata退了? 无所谓,GBASE会出手

近期&#xff0c;就在2月15日&#xff0c;国内IT界有搞出个大瓜&#xff0c;Teradata以对中国当前及未来商业环境的不确定性&#xff0c;慎重考虑后决定退出中国运营&#xff0c;后续将进入中国公司关闭程序。Teradata是一家有着40多年历史的数据仓库企业&#xff0c;被业界专业…

动态规划从入门到精通-蓝桥杯

一、了解动态规划1.简单来说动态规划是一种状态转移与递推2.例题引入——最少硬币问题有多个不同面值的硬币(任意面值)&#xff1b; 数量不限&#xff1b; 输入金额S&#xff0c;输出最少硬币组合。 &#xff08;回顾用贪心求解硬币问题。&#xff09;贪心法硬币面值1、2、5。支…

2023年中职网络安全竞赛跨站脚本渗透解析-2(超详细)

跨站脚本渗透 任务环境说明:需求环境可私信博主! 服务器场景:Server2126(关闭链接)服务器场景操作系统:未知访问服务器网站目录1,根据页面信息完成条件,将获取到弹框信息作为flag提交;访问服务器网站目录2,根据页面信息完成条件,将获取到弹框信息作为flag提交;访问…