Redis:发布(pub)与订阅(sub)实战

前言

Redis发布订阅(Pub/Sub)是Redis提供的一种消息传递机制,它使用“发布者-订阅者”(publisher-subscriber)模式来处理消息传递。在这种模式下,发布者将消息发布到一组订阅者中,而无需关心谁是订阅者,也不需要知道订阅者是否收到了消息。
在这里插入图片描述

发布者和订阅者模式允许多个客户端之间建立一个复杂的通信拓扑。在这种模式下,发布者可以发布消息到一个特定的主题,订阅者可以订阅一个或多个主题,并在发布者发布消息时收到消息。由于发布者和订阅者不必直接连接,因此发布者和订阅者可以完全独立地运行,只要它们都连接到Redis实例即可。

Redis发布订阅支持多种消息类型,包括文本、字节数组和数字等。 Redis还支持订阅者识别特定消息,通过模式匹配功能,可以基于主题模式或模式来检索消息。Redis还提供了许多API来帮助您实现发布/订阅模式,因此您可以使用Redis的发布/订阅功能来构建分布式应用程序。

Redis Pub/Sub(发布/订阅) 命令

Redis发布/订阅(Pub/Sub)分为两种

  • 第一种基于频道(Channel)的发布/订阅。
  • 第二种基于模式(pattern)的发布/订阅

确实,Redis提供了一系列的Pub/Sub命令来支持基于频道和基于模式的发布/订阅模式。以下是一些常用的Pub/Sub命令:

基于频道的发布/订阅

发布消息到指定频道

PUBLISH channel message

例如:

PUBLISH my-channel "Hello, Redis!"

这将向名为my-channel的频道发布消息"Hello, Redis!"。

订阅一个或多个频道

SUBSCRIBE channel channel ...

例如:

SUBSCRIBE my-channel your-channel

这将订阅my-channelyour-channel两个频道。

取消订阅一个或多个频道

UNSUBSCRIBE [channel channel ...]

例如:

UNSUBSCRIBE my-channel your-channel

这将取消订阅my-channelyour-channel两个频道。

基于模式的发布/订阅

订阅一个或多个匹配模式

PSUBSCRIBE pattern pattern ...

例如:

PSUBSCRIBE news-*

这将订阅所有以news-开头的频道。

取消订阅一个或多个匹配模式

PUNSUBSCRIBE [pattern pattern ...]

例如:

PUNSUBSCRIBE news-*

这将取消订阅所有以news-开头的频道。

注意:Pub/Sub命令可以在客户端和服务器之间进行通信,用于实现消息的发布和订阅。这些命令是异步执行的,发送命令后,订阅者将在接收到消息时收到通知。 Pub/Sub是一个强大的工具,用于实现实时消息传递和事件通知。

实战示例

基于MessageListener实现

创建消息接收者

创建一个接收消息的Bean。

package com.example.demo.redis;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Component;/*** 实现MessageListener的监听类*/
@Slf4j
@Component
public class RedisMessageSubscriber implements MessageListener {@Autowiredprivate MessageProcessor messageProcessor;@Overridepublic void onMessage(Message message, byte[] pattern) {String channel = new String(message.getChannel());String body = new String(message.getBody());log.info("@@ 当前执行的方法:onMessage");// 处理消息messageProcessor.processMessage(channel, body);}}

创建消息处理器

创建一个处理接收到的消息的Bean。

package com.example.demo.redis;
import org.springframework.stereotype.Service;@Service
public class MessageProcessor {public void processMessage(String channel, String message) {System.out.println("Received message: " + message + " from channel: " + channel);// 在这里进行具体的消息处理逻辑}
}

创建消息发送者

创建一个发送消息的Bean。

Redis有两种发布/订阅模式:

  • 基于频道(Channel)的发布/订阅
  • 基于模式(pattern)的发布/订阅
package com.example.demo.redis;// RedisMessagePublisher.javaimport org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;@Component
public class RedisMessagePublisher {@Autowiredprivate RedisTemplate<String, String> redisTemplate;public void publishMessage(String channel, String message) {// 基于模式(pattern)的发布/订阅// redisTemplate.convertAndSend("your-pattern-channel-1", "Hello, Redis!");// 基于频道(Channel)的发布/订阅redisTemplate.convertAndSend(channel, message);}
}

使用消息发送者发送消息

在需要发送消息的地方注入RedisMessagePublisher并使用它来发送消息。

package com.example.demo.redis;// MessageController.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api/message")
public class MessageController {@Autowiredprivate RedisMessagePublisher messagePublisher;@GetMapping("/send")public String sendMessage(@RequestParam(value = "channel") String channel , @RequestParam(value = "messgage") String messgage) {messagePublisher.publishMessage("your-channel", "Hello, Redis!");messagePublisher.publishMessage(channel, messgage);return "Message sent successfully!";}
}

相关原理说明

  • 发布/订阅模型: Redis提供了一种发布/订阅(Pub/Sub)模型,其中消息发送者(发布者)将消息发送到一个或多个通道,而消息接收者(订阅者)则监听一个或多个通道以接收消息。
  • 消息监听器: RedisMessageSubscriber 实现了 MessageListener 接口,它监听指定通道上的消息。在这里,我们将接收到的消息传递给 MessageProcessor 进行处理。
  • 消息处理器: MessageProcessor 是一个简单的服务,用于处理接收到的消息。在实际应用中,你可以在这里添加业务逻辑来处理消息。
  • 消息发布者: RedisMessagePublisher 用于发布消息到指定的通道。在 sendMessage 方法中,我们使用 convertAndSend 方法将消息发送到名为 “your-channel” 的通道。
  • 消息发送端点: MessageController 是一个简单的REST控制器,用于触发消息发送。在这里,我们通过调用 messagePublisher.publishMessage 来发送消息。

总体来说,这个实现充分利用了Redis的发布/订阅功能,通过将消息发送者、消息接收者和消息处理器分离,使系统更加模块化和灵活。

RedisConfig配置

package com.example.demo.redis;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;@Slf4j
@Configuration
public class RedisConfig {/*** 配置订阅* 基于MessageListenerAdapter和RedisMessageListenerContainer* @param redisMessageSubscriber* @return*/@Beanpublic MessageListenerAdapter messageListenerAdapter(RedisMessageSubscriber redisMessageSubscriber) {return new MessageListenerAdapter(redisMessageSubscriber, "handleMessage");}@Beanpublic RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory,MessageListenerAdapter messageListenerAdapter) {RedisMessageListenerContainer container = new RedisMessageListenerContainer();container.setConnectionFactory(connectionFactory);// 添加消息监听器和监听的频道// 基于频道的发布/订阅:container.addMessageListener(messageListenerAdapter, new ChannelTopic("your-channel"));// 基于模式的发布/订阅:container.addMessageListener(messageListenerAdapter, new PatternTopic("your-pattern-*"));return container;}/*** 基于MessageListener的配置* 直接使用RedisMessageSubscriber* @param connectionFactory* @param redisMessageSubscriber* @return*/@Beanpublic RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory,  RedisMessageSubscriber redisMessageSubscriber) {RedisMessageListenerContainer container = new RedisMessageListenerContainer();container.setConnectionFactory(connectionFactory);// 在这里设置你的动态频道名称,可以从配置文件或其他地方获取String dynamicChannel = "your-channel";// 基于频道的发布/订阅:ChannelTopic channelTopic = new ChannelTopic(dynamicChannel);// 基于模式的发布/订阅:// container.addMessageListener(redisMessageSubscriber, new PatternTopic("your-pattern-*"));// 添加消息监听器和监听的动态频道container.addMessageListener(redisMessageSubscriber, channelTopic);return container;}//    /**
//     * 多频道示例
//     * @param connectionFactory
//     * @param redisMessageSubscriber
//     * @return
//     */
//    @Bean
//    public RedisMessageListenerContainer redisMessageListenerContainerMoreTopic(
//            RedisConnectionFactory connectionFactory,
//            RedisMessageSubscriber redisMessageSubscriber
//    ) {
//        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
//        container.setConnectionFactory(connectionFactory);
//
//        // 在这里设置你的动态频道名称列表,可以从配置文件或其他地方获取
//        List<String> dynamicChannels = Arrays.asList("channel1", "channel2", "channel3");
//
//        // 创建包含所有频道的ChannelTopic列表
//        List<ChannelTopic> channelTopics = createChannelTopics(dynamicChannels);
//
//        // 添加消息监听器和监听的多个频道
//        for (ChannelTopic channelTopic : channelTopics) {
//            container.addMessageListener(redisMessageSubscriber, channelTopic);
//        }
//
//        return container;
//    }
//
//    private List<ChannelTopic> createChannelTopics(List<String> channelNames) {
//        // 使用动态频道名称创建ChannelTopic列表
//        List<ChannelTopic> channelTopics = new ArrayList<>();
//        for (String channelName : channelNames) {
//            channelTopics.add(new ChannelTopic(channelName));
//        }
//        return channelTopics;
//    }
}

这段代码是用于配置并创建 RedisMessageListenerContainer 的方法。RedisMessageListenerContainer 是 Spring Data Redis 提供的一个用于监听 Redis 消息的容器。以下是对代码的详细解释:

方法签名

  • RedisConnectionFactory connectionFactory:这是用于创建 Redis 连接的工厂。
  • RedisMessageSubscriber redisMessageSubscriber:这是一个 Redis 消息订阅者,用于处理接收到的消息。

创建 RedisMessageListenerContainer 实例

RedisMessageListenerContainer container = new RedisMessageListenerContainer(); 
container.setConnectionFactory(connectionFactory);
  • 创建一个新的 RedisMessageListenerContainer 实例。
  • connectionFactory 设置为容器的连接工厂,用于创建连接到 Redis 的连接。

设置动态频道名称

String dynamicChannel = "your-channel";
  • 定义一个动态频道名称,可以从配置文件或其他地方获取。

创建 ChannelTopic 对象

ChannelTopic channelTopic = new ChannelTopic(dynamicChannel);
  • 创建一个 ChannelTopic 对象,表示基于频道的发布/订阅,其中 dynamicChannel 是频道名称。

添加消息监听器和频道

container.addMessageListener(redisMessageSubscriber, channelTopic);
  • redisMessageSubscriber 添加为消息监听器,用于处理接收到的消息。
  • 指定要监听的频道,这里使用了基于频道的发布/订阅模式。

返回 RedisMessageListenerContainer 实例

return container;
  • 返回配置好的 RedisMessageListenerContainer 实例。

通过以上步骤,这段代码的目的是创建一个配置好的 RedisMessageListenerContainer,该容器已设置好连接工厂、消息监听器以及要监听的动态频道。当 Redis 中的指定频道发布消息时,redisMessageSubscriberonMessage 方法将被调用来处理消息。这是一种基于频道的发布/订阅模式,允许应用程序实时地接收并处理消息。

自定义监听的回调函数

创建消息接收者

不需要实现MessageListener接口

package com.example.demo.redis;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** 自定义的监听类*/
@Slf4j
@Component
public class RedisMessageCustomSubscriber {@Autowiredprivate MessageProcessor messageProcessor;/*** 自定义的回调函数* @param message* @param channel*/public void handleMessage(String message, String channel) {log.info("@@ 当前执行的方法:handleMessage");messageProcessor.processMessage(channel, message);}
}

RedisConfig配置

package com.example.demo.redis;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;@Slf4j
@Configuration
public class RedisConfig {/*** 配置订阅* 基于MessageListenerAdapter和RedisMessageListenerContainer* @param redisMessageSubscriber* @return*/@Beanpublic MessageListenerAdapter messageListenerAdapter(RedisMessageSubscriber redisMessageSubscriber) {return new MessageListenerAdapter(redisMessageSubscriber, "handleMessage");}@Beanpublic RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory,MessageListenerAdapter messageListenerAdapter) {RedisMessageListenerContainer container = new RedisMessageListenerContainer();container.setConnectionFactory(connectionFactory);// 添加消息监听器和监听的频道// 基于频道的发布/订阅:container.addMessageListener(messageListenerAdapter, new ChannelTopic("your-channel"));// 基于模式的发布/订阅:container.addMessageListener(messageListenerAdapter, new PatternTopic("your-pattern-*"));return container;}//    /**
//     * 基于MessageListener的配置
//     * 直接使用RedisMessageSubscriber
//     * @param connectionFactory
//     * @param redisMessageSubscriber
//     * @return
//     */
//    @Bean
//    public RedisMessageListenerContainer redisMessageListenerContainer(
//            RedisConnectionFactory connectionFactory,  RedisMessageSubscriber redisMessageSubscriber) {
//
//        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
//        container.setConnectionFactory(connectionFactory);
//
//        // 在这里设置你的动态频道名称,可以从配置文件或其他地方获取
//        String dynamicChannel = "your-channel";
//
//        // 基于频道的发布/订阅:
//        ChannelTopic channelTopic = new ChannelTopic(dynamicChannel);
//
//        // 基于模式的发布/订阅:
//        // container.addMessageListener(redisMessageSubscriber, new PatternTopic("your-pattern-*"));
//
//        // 添加消息监听器和监听的动态频道
//        container.addMessageListener(redisMessageSubscriber, channelTopic);
//
//        return container;
//    }//    /**
//     * 多频道示例
//     * @param connectionFactory
//     * @param redisMessageSubscriber
//     * @return
//     */
//    @Bean
//    public RedisMessageListenerContainer redisMessageListenerContainerMoreTopic(
//            RedisConnectionFactory connectionFactory,
//            RedisMessageSubscriber redisMessageSubscriber
//    ) {
//        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
//        container.setConnectionFactory(connectionFactory);
//
//        // 在这里设置你的动态频道名称列表,可以从配置文件或其他地方获取
//        List<String> dynamicChannels = Arrays.asList("channel1", "channel2", "channel3");
//
//        // 创建包含所有频道的ChannelTopic列表
//        List<ChannelTopic> channelTopics = createChannelTopics(dynamicChannels);
//
//        // 添加消息监听器和监听的多个频道
//        for (ChannelTopic channelTopic : channelTopics) {
//            container.addMessageListener(redisMessageSubscriber, channelTopic);
//        }
//
//        return container;
//    }
//
//    private List<ChannelTopic> createChannelTopics(List<String> channelNames) {
//        // 使用动态频道名称创建ChannelTopic列表
//        List<ChannelTopic> channelTopics = new ArrayList<>();
//        for (String channelName : channelNames) {
//            channelTopics.add(new ChannelTopic(channelName));
//        }
//        return channelTopics;
//    }
}

这段代码配置了两个 @Bean 方法,一个用于创建 MessageListenerAdapter 实例,另一个用于创建 RedisMessageListenerContainer 实例。以下是详细解释:

创建 MessageListenerAdapter 实例

@Bean
public MessageListenerAdapter messageListenerAdapter(RedisMessageSubscriber redisMessageSubscriber) {return new MessageListenerAdapter(redisMessageSubscriber, "handleMessage");
}
  • 通过 @Bean 注解创建一个 MessageListenerAdapter 实例。
  • RedisMessageSubscriber 对象传递给构造函数,表示这个适配器将调用 RedisMessageSubscriber 的方法来处理消息。
  • 第二个参数 "handleMessage" 表示要调用的消息处理方法的名称。

创建 RedisMessageListenerContainer 实例

@Bean
public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory,MessageListenerAdapter messageListenerAdapter
) {RedisMessageListenerContainer container = new RedisMessageListenerContainer();container.setConnectionFactory(connectionFactory);
  • 通过 @Bean 注解创建一个 RedisMessageListenerContainer 实例。
  • RedisConnectionFactory 传递给构造函数,表示这个容器将使用的连接工厂。

添加消息监听器和频道

// 添加消息监听器和监听的频道
// 基于频道的发布/订阅:
container.addMessageListener(messageListenerAdapter, new ChannelTopic("your-channel"));// 基于模式的发布/订阅:
container.addMessageListener(messageListenerAdapter, new PatternTopic("your-pattern-*"));
  • 使用 container.addMessageListener 方法添加消息监听器(messageListenerAdapter)。
  • 第一个参数是消息监听器适配器,它会调用 RedisMessageSubscriberhandleMessage 方法来处理消息。
  • 第二个参数是 ChannelTopic 对象,表示基于频道的发布/订阅模式,监听指定的频道。
  • 第三个参数是 PatternTopic 对象,表示基于模式的发布/订阅模式,监听指定模式的频道。

返回 RedisMessageListenerContainer 实例

return container;
  • 返回配置好的 RedisMessageListenerContainer 实例。

通过这样的配置,RedisMessageListenerContainer 已经设置好了连接工厂和消息监听器,并分别基于频道和基于模式的发布/订阅模式来监听相应的消息。当 Redis 中的指定频道发布消息时,handleMessage 方法将被调用来处理消息。

区别

MessageListenerAdapterRedisMessageListenerContainer 是 Spring Data Redis 提供的两个重要组件,用于实现 Redis 消息监听的机制。

MessageListenerAdapter

MessageListenerAdapter 是一个适配器,用于将普通的 Java 对象(POJO)转换为 Redis 消息监听器。它通过反射调用目标对象的方法来处理接收到的消息。在你的 POJO 类中,你可以定义一个或多个方法来处理不同类型的消息。

主要特点和用法:

  • 将普通的 Java 对象转换为 Redis 的消息监听器。
  • 可以指定调用目标对象的特定方法来处理消息。
  • 通过设置消息转换器,可以支持多种消息格式,如 JSON、XML 等。
  • 提供了一种简化消息处理逻辑的方式,避免了直接实现 MessageListener 接口的繁琐性。

RedisMessageListenerContainer

RedisMessageListenerContainer 是 Spring 提供的容器,用于管理 Redis 消息的监听器。它可以注册一个或多个消息监听器,并在接收到消息时调用相应的处理方法。该容器还负责管理连接到 Redis 的连接工厂,以及监听的频道或模式。

主要特点和用法:

  • 管理 Redis 连接工厂,确保连接的创建和关闭。
  • 注册消息监听器,并在接收到消息时调用相应的处理方法。
  • 支持基于频道和基于模式的发布/订阅模式。
  • 提供了灵活的配置选项,如消息转换器、错误处理器等。

总体而言,MessageListenerAdapterRedisMessageListenerContainer 是一对重要的组件,它们使得在 Spring 应用中实现 Redis 消息监听变得更加简单和灵活。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于MATLAB的图像融合设计

摘 要 图像融合能够将不同类型传感器获取的同一对象的图像数据进行空间配准。并且采用一定的算法将不同类型的传感器获取的同一对象的图像数据所含用的信息优势或互补性有机地结合起来产生的新的图像数据。这种新数据含有所研究对象的更多信息表征&#xff0c;与单一图像相对比…

learn C++ NO.13——list

前言 本文将从list的使用&#xff0c;再到根据sgi库对于list实现作为参考模拟实现一下list。通过模拟实现来增加对它的理解。 介绍list list是一个由带头双向循环链表实现的STL容器&#xff0c;它提供常规时间内对数据进行插入和删除操作。 list在内存中存储不连续的空间存储…

计算机组成原理(第二次笔记)

各种码 真值 (书写用)&#xff1a; 将用“”、“-” 表示正负的二进制数称为真值 机器不能识别书写格式&#xff0c;故用“0/1”表示“/-”符号。 机器码 (机器内部使用)&#xff1a; 将符号和数值一起编码表示的二进制数称为机器码。 常用机器码&#xff1a;原码、 反码、 补…

SpringCloud Alibaba之Nacos服务注册和配置中心

&#xff08;学习笔记&#xff09;nacos-server版本&#xff1a;2.2.3 总体介绍&#xff1a; 1、Nacos介绍 官网&#xff1a;Nacos官网| Nacos 配置中心 | Nacos 下载| Nacos 官方社区 | Nacos 官网 Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service的首字…

前端网页代码编辑器 Monaco Editor

前端网页代码编辑器 Monaco Editor Monaco Editor Monaco Editor 是由 Microsoft 开发的一款基于 Web 技术的开源代码编辑器&#xff0c;它是 Visual Studio Code 编辑器的核心。Monaco Editor 可以嵌入到网页中&#xff0c;提供类似于 Visual Studio Code 的编辑体验。 官方…

MySQL聚合统计

【数据库】MySQL聚合统计 王笃笃-CSDN博客https://blog.csdn.net/wangduduniubi?typeblog显示平均工资低于2000的部门和它的平均工资 mysql> select deptno,avg(sal) deptavg from emp group by deptno; --------------------- | deptno | deptavg | --------------…

信通院发布首个《大模型媒体生产与处理》标准,阿里云智能媒体服务作为业界首家“卓越级”通过

中国信通院近期正式发布《大模型驱动的媒体生产与处理》标准&#xff0c;阿里云智能媒体服务&#xff0c;以“首批首家”通过卓越级评估&#xff0c;并在9大模块50余项测评中表现为“满分”。 当下&#xff0c;AI大模型的快速发展带动了爆发式的海量AI运用&#xff0c;这其中&a…

职场女性的心灵救赎:数业智能心大陆照亮新曙光

近年来&#xff0c;职场女性抑郁问题愈发凸显。数业智能心大陆的AI心理疗愈平台数据显示&#xff0c;超八成职场女性曾感到抑郁。90 后职场女性的心理健康状况尤其令人担忧&#xff0c;随着年龄层的下降&#xff0c;职场女性中出现抑郁状态的比例呈现明显的上升趋势。 职场女性…

Jetpack Compose Side Effects in Details 副作用的详细信息

What is Side Effect’s? 副作用是什么&#xff1f; Side Effects is a change in the state of the application that occurs outside the scope of the composable function and is not related to the UI. In non-UI related state changes, our screen may recompose mor…

828华为云征文 | 使用华为云X实例部署图数据库Virtuoso并存储6500万条大数据的完整过程与性能测评

前言 在大数据时代&#xff0c;图数据库以其强大的关系处理能力在复杂网络、社交媒体分析、知识图谱等领域得到了广泛应用。而在云计算的蓬勃发展下&#xff0c;使用云服务器进行图数据库的部署与管理变得更加方便高效。本篇文章将详细介绍如何在华为云X实例上部署开源图数据…

中秋假期也能及时回应客户:微信聚合管理系统,自动回复

中秋佳节是阖家团圆的日子&#xff0c;很多人选择在此期间休息放松。但作为一名职场人士&#xff0c;如何在假期中不遗漏客户咨询&#xff1f; 不妨试试这个WeBot助手&#xff0c;你可以进行微信自动回复设置&#xff0c;轻松实现假期与工作两不误。 同一界面聚合多个账号 通…

HOT 100(七)栈、堆、贪心算法

一、栈 1、每日温度 使用单调递减栈来解决。主要思路是遍历temperatures数组&#xff0c;利用栈来存储还没有找到比当前温度高的天数的索引。当遇到比栈顶索引所对应温度更高的温度时&#xff0c;就可以确定当前这一天的温度比之前那一天高。索引的差值就是等待的天数。 求一…

使用c#制作一个小型桌面程序

封装dll 首先使用visual stdio 创建Dll新项目,然后属性管理器导入自己的工程属性表&#xff08;如果没有可以参考visual stdio 如何配置opencv等其他环境&#xff09; 创建完成后 系统会自动生成一些文件&#xff0c;其中 pch.cpp 先不要修改&#xff0c;pch.h中先导入自己需…

Unet改进31:添加Star_Block(2024最新改进方法)|紧凑的网络结构和高效的运算

本文内容:在不同位置添加Star_Block 目录 论文简介 1.步骤一 2.步骤二 3.步骤三 4.步骤四 论文简介 最近的研究引起了人们对网络设计中尚未开发的“星型操作”(元素智能乘法)潜力的关注。虽然有很多直观的解释,但其应用背后的基本原理在很大程度上仍未被探索。我们的研…

旅游网站设计与实现:SpringBoot技术手册

第三章 系统分析 开发一个系统首先要对系统进行分析&#xff0c;是开发者针对系统实际客户对软件应用的一个调查访问和研究&#xff0c;弄清用户对软件需求的具体要求&#xff0c;同时开发者还要对系统开发的经济和可技术上是否可行进行分析&#xff0c;并确定系统开发的成本和…

OZON电子产品大幅增长,OZON跨境PS5销量激增

Top1 存储卡 Карта памяти Canvas Select Plus 128 ГБ 商品id&#xff1a;1548303593 月销量&#xff1a;2131 欢迎各位卖家朋友点击这里&#xff1a; &#x1f449; D。DDqbt。COm/74rD 免费体验 随着智能手机和平板电脑的普及&#xff0c;用户对于存储空…

C++笔记---继承(上)

1. 继承的简单介绍 1.1 继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许我们在保持原有类特性的基础上进行扩展&#xff0c;增加方法(成员函数)和属性(成员变量)&#xff0c;这样产生新的类&#xff0c;称派生类。 继承呈…

使用LDAP登录GitLab

使用LDAP登录GitLab gitlab.rb 配置如下 gitlab_rails[ldap_enabled] true #gitlab_rails[prevent_ldap_sign_in] false###! **remember to close this block with EOS below** gitlab_rails[ldap_servers] YAML.load <<-EOSmain:label: LDAPhost: 172.16.10.180port:…

python环境安装

一、下载开发IDE https://www.jetbrains.com/pycharm/download/?sectionwindows 下载:conda Download Now | Anaconda 重新打开PyCharm Community Edition 2024.2.1 新建项目&#xff1a;pythonProject1 编写python 文件时没有提示&#xff1a;错误:未选择 Python 解释器。请…

云轴科技ZStack 获鲲鹏应用创新大赛2024上海赛区决赛一等奖

9月13日&#xff0c;鲲鹏应用创新大赛2024上海赛区决赛成功举办。经评委专家从方案创新性、技术领先性、商业前景以及社会价值四个维度严格评审&#xff0c;云轴科技ZStack参赛作品《ZStack鲲鹏原生开发方案》荣获上海赛区企业赛——原生开发赛道&#xff08;互联网&#xff09…