spring-bus消息总线的使用

文章目录

  • 依赖
  • bus应用
    • 接口
    • 用到的封装参数类
  • 接收的应用
    • 监听器
    • 定义的事件类
  • 使用bus
    • 定义bus远程调用
    • A应用数据更新后通过bus数据同步给B应用

依赖

   <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-bus-amqp</artifactId>
    </dependency>

bus应用

  • 类似于生产者

接口

  • 供内部其他应用使用,远程调用该接口实现各应用之间数据同步
  • 参数1定义事件,参数2定义操作具体crud,参数3定义传参数据,参数4定义给哪个应用(nacos注册的应用名)同步数据
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.xyc.sms.common.bus.events.DataSyncEventEnum;
import com.xyc.sms.common.bus.events.DataSyncEventFactory;
import com.xyc.sms.common.bus.events.DataSyncOperateTypeEnum;
import com.xyc.sms.common.entity.Result;
import org.springframework.cloud.bus.ServiceMatcher;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/**
 * 数据同步通知事件控制器,该事件主要用于平台中常规的数据同步通知,
 * 需要用于其他功能请新增类
 * 需要增加同步的方式请在{@link DataSyncEventEnum}增加事件枚举
 * 同时在{@link com.xyc.sms.common.bus.events.dataSync}下增加事件类,新增的事件类需要继承{@link com.xyc.sms.common.bus.events.DataSyncEvent}
 */
@RestController
@RequestMapping("/default")
public class DataSyncNotifyEventController {

    private static final Log logger = LogFactory.get();

    @Resource
    private ServiceMatcher busServiceMatcher;
    @Resource
    private ApplicationEventPublisher applicationEventPublisher;

    /**
     * 发布数据同步通知事件
     *
     * @param eventEnum   事件枚举,可通过枚举找到对应的事件类
     * @param operateType 操作类型枚举
     * @param obj         需要处理的消息
     * @param destination 目的地,为null则是广播给所有该事件的监听器
     * @return 发布结果
     */
    @PostMapping("/publish/{eventEnum}/{operateType}")
    public Result publishDataSyncNotifyEvent(@PathVariable("eventEnum") DataSyncEventEnum eventEnum,
                                             @PathVariable("operateType") DataSyncOperateTypeEnum operateType,
                                             @RequestBody Object obj,
                                             @RequestParam(value = "destination", required = false) String destination) {
        try {
            applicationEventPublisher.publishEvent(DataSyncEventFactory.getInstanceForEvent(
                    eventEnum,
                    operateType,
                    obj,
                    busServiceMatcher.getServiceId(),
                    destination));
            return Result.returnSuccessWithMsg("success");
        } catch (Exception e) {
            logger.error(e);
            return Result.returnFail(e.getMessage());
        }
    }
}
  • 事件工厂类
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;

public class DataSyncEventFactory {

    private static final ObjectMapper OM = new ObjectMapper();

    /**
     * 通过事件的类模板获取构造器并调用,生成事件的实体类
     *
     * @param operateType        操作类型
     * @param source             事件原数据
     * @param originService      原服务
     * @param destinationService 目标服务
     * @return 事件实体类
     * @throws NoSuchMethodException     通过类模板无法找到相应的构造方法所抛出的异常
     * @throws InvocationTargetException 构造器创建实例可能出现的调用目标异常
     * @throws InstantiationException    构造器创建实例可能出现的实例化异常
     * @throws IllegalAccessException    构造器创建实例可能出现的无法访问异常
     * @throws IOException               json转化出现IO的异常
     * @throws ClassNotFoundException    通过类名{@link DataSyncEventEnum#getEventClassName()}没有找到对应类
     */
    public static DataSyncEvent<?> getInstanceForEvent(DataSyncEventEnum eventEnum,
                                                       DataSyncOperateTypeEnum operateType,
                                                       Object source,
                                                       String originService,
                                                       String destinationService)
            throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException {
        Constructor<?>[] constructors = DataSyncEventFactory.getEventClass(eventEnum).getDeclaredConstructors();
        Constructor<?> constructor = Arrays.stream(constructors).filter(c -> c.getParameterCount() == 4).findFirst().orElseThrow(
                NoSuchMethodException::new);
        // 值转化
        Object o = OM.readValue(OM.writeValueAsString(source), constructor.getParameterTypes()[1]);
        return (DataSyncEvent<?>) constructor.newInstance(operateType, o, originService, destinationService);
    }

    private static Class<?> getEventClass(DataSyncEventEnum eventEnum) throws ClassNotFoundException {
        return Class.forName(eventEnum.getEventClassName());
    }
}

用到的封装参数类

在这里插入图片描述

  • 定义各事件的枚举(只定义全类限定名称)
public enum DataSyncEventEnum {

    /**
     * 黑名单同步,参数为事件的类型名,注意需要使用全限定类名
     * @see com.xyc.sms.common.bus.events.dataSync.BlackListSyncEvent
     */
    BLACKLIST_SYN("com.xyc.sms.common.bus.events.dataSync.BlackListSyncEvent"),
    /**
     * 路由同步
     * @see com.xyc.sms.common.bus.events.dataSync.RouteSyncEvent
     */
    ROUTE_SYN("com.xyc.sms.common.bus.events.dataSync.RouteSyncEvent");

    /**
     * 事件类型名
     * @see DataSyncEvent 该抽象类的实现类
     */
    private final String eventClassName;

    DataSyncEventEnum(String eventClassName) {
        this.eventClassName = eventClassName;
    }

    public String getEventClassName() {
        return eventClassName;
    }
}
  • 定义crud操作枚举
public enum DataSyncOperateTypeEnum implements Serializable {
    ADD, UPD, DEL
}
  • 推送的事件类
/**
 * 数据同步通知事件,作为一般通用事件使用,如需要特殊处理建议新增事件
 */
public abstract class DataSyncEvent<T> extends RemoteApplicationEvent {

    /**
     * 事件数据
     */
    private DataSync<T> dataSync;

    public DataSync<T> getDataSync() {
        return dataSync;
    }

    public void setDataSync(DataSync<T> dataSync) {
        this.dataSync = dataSync;
    }

    /**
     * 基础构造器
     *
     * @param source             引发事件的原始数据
     * @param originService      引发事件的原始服务
     * @param destinationService 事件的目标服务
     */
    public DataSyncEvent(DataSync<T> source, String originService, String destinationService) {
        super(source, originService, destinationService);
        this.dataSync = source;
    }

    /**
     * 事件的日志打印,会在监听器监听到事件时输出打印
     * 结果尽可能不要有换行,保证日志输出在一行内
     * 该方法可以在子类中重写
     *
     * @return 日志
     */
    public String logPrint() {
        return String.format("{\"originService\":\"%s\",\"destinationService\":\"%s\",\"id\":\"%s\",\"dataSync\":%s,\"timestamp\":\"%s\"}", this.getId(), this.getOriginService(), this.getDestinationService(), Objects.nonNull(this.dataSync) ? this.dataSync.toString() : "null", this.getTimestamp());
    }

    /**
     * 数据同步的原始数据封装
     */
    public static class DataSync<T> implements Serializable {
        private DataSyncOperateTypeEnum operateType;
        private T data;

        public DataSync() {
        }

        public DataSync(DataSyncOperateTypeEnum operateType, T data) {
            this.operateType = operateType;
            this.data = data;
        }

        public DataSyncOperateTypeEnum getOperateType() {
            return operateType;
        }

        public T getData() {
            return data;
        }

        @Override
        public String toString() {
            return "{\"operateType\":" +
                    operateType
                    + ",\"data\":" +
                    data
                    + "}";
        }
    }
}
  • 应用枚举
/**
 * 服务枚举
 */
public enum ServiceEnum {
    SMS_BLACK_API("sms-black-api"),
    SMS_RULES("sms-rules");

    public final String serviceName;

    ServiceEnum(String serviceName) {
        this.serviceName = serviceName;
    }
}

接收的应用

  • 类似于消费者

监听器

  • 推送过来的操作枚举类crud的值,决定执行哪个crud的具体方法
  • 该类放在接收的应用中,其他顶部继承的类放在common包中即可
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.xyc.sms.common.bus.DataSyncListener;
import com.xyc.sms.common.bus.events.dataSync.RouteSyncEvent;
import com.xyc.sms.common.entity.sms.Route;
import com.xyc.sms.rules.dao.boss.RouteMapper;
import com.xyc.sms.rules.data.RuleSymbol;
import com.xyc.sms.rules.service.SynService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 路由同步通知监听器
 */
@Component
public class RouteSynNotifyListener extends DataSyncListener<RouteSyncEvent, List<Route>> {

    private static final Log log = LogFactory.get();

    @Autowired
    private RouteMapper routeMapper;

    @Autowired
    private SynService synService;

    @Override
    public void handleByADD(List<Route> data) {
        Optional.ofNullable(data).ifPresent(ls -> {
            if (ls.isEmpty()) {
                return;
            }

            long l = System.currentTimeMillis();

            String time = DateUtil.formatDateTime(ls.get(0).getCreateTime());
            List<Route> list = routeMapper.selectByCreatetime(time);
            if (CollectionUtil.isEmpty(list)) {
                return;
            }

            // 加载到内存中
            list.forEach(r -> RuleSymbol.RouteMap.put(r.getId(), r));
            synService.transformRoute(list, (s, r) -> RuleSymbol.RouteChannelMap.put(s, r));
            log.info("RouteSynNotifyListener - {} - add | createTime:{}", (System.currentTimeMillis() - l), time);
        });
    }

    @Override
    public void handleByUPD(List<Route> data) {
        // 流程还是先删除后新增的方式
        Optional.ofNullable(data).ifPresent(ls -> {
            List<Integer> collect = ls.stream()
                    .map(Route::getId)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
            if (collect.isEmpty()) {
                return;
            }

            long l = System.currentTimeMillis();

            // 如果有,先删除
            List<Route> c = collect.stream()
                    .map(RuleSymbol.RouteMap::get)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
            if (!c.isEmpty()) {
                synService.transformRoute(c, (s, r) -> RuleSymbol.RouteChannelMap.remove(s, r));
            }


            // 如果有,再加入
            List<Route> list = routeMapper.selectById(collect);
            if (!list.isEmpty()) {
                list.forEach(r -> RuleSymbol.RouteMap.put(r.getId(), r));
                synService.transformRoute(list, (s, r) -> RuleSymbol.RouteChannelMap.put(s, r));
            }
            log.info("RouteSynNotifyListener - {} - update | {}", (System.currentTimeMillis() - l), collect);
        });
    }

    @Override
    public void handleByDEL(List<Route> data) {
        Optional.ofNullable(data).ifPresent(ls -> {
            long l = System.currentTimeMillis();
            List<Route> collect = ls.stream()
                    .map(r -> RuleSymbol.RouteMap.remove(r.getId()))
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());

            if (collect.isEmpty()) {
                return;
            }
            synService.transformRoute(collect, (s, r) -> RuleSymbol.RouteChannelMap.remove(s));
            log.info("RouteSynNotifyListener - {} - remove", (System.currentTimeMillis() - l));
        });
    }
}
  • 继承的抽象监听类
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.xyc.sms.common.bus.events.DataSyncEvent;
import org.springframework.context.ApplicationListener;

/**
 * 数据同步事件监听器
 * 需要具体的子类实现,并注册到spring容器中
 *
 * @param <T> 数据同步件
 */
public abstract class DataSyncListener<T extends DataSyncEvent<D>, D> implements ApplicationListener<T> {

    private static final Log logger = LogFactory.get();

    @Override
    public void onApplicationEvent(T event) {
        logger.info("[DataSyncListener][onApplicationEvent] trigger event - {} - {}", event.getClass().getName(), event.logPrint());
        try {
            triggerEvent(event);
        } catch (Exception e) {
            logger.error(e);
        }
    }

    /**
     * 触发监听,处理事件
     *
     * @param event 事件
     */
    public void triggerEvent(T event) {
        DataSyncEvent.DataSync<D> source = event.getDataSync();
        switch (source.getOperateType()) {
            case ADD:
                handleByADD(source.getData());
                return;
            case UPD:
                handleByUPD(source.getData());
                return;
            case DEL:
                handleByDEL(source.getData());
                return;
            default:
        }
    }

    /**
     * 处理添加事件
     * 由子类实现
     *
     * @param data 需要处理的数据
     */
    public abstract void handleByADD(D data);

    /**
     * 处理修改事件
     * 由子类实现
     *
     * @param data 需要处理的数据
     */
    public abstract void handleByUPD(D data);

    /**
     * 处理删除事件
     * 由子类实现
     *
     * @param data 需要处理的数据
     */
    public abstract void handleByDEL(D data);
}

定义的事件类

  • 上面封装的事件枚举所记录的是该类的全类限定名称
package com.xyc.sms.common.bus.events.dataSync;

import com.xyc.sms.common.bus.events.DataSyncEvent;
import com.xyc.sms.common.bus.events.DataSyncOperateTypeEnum;
import com.xyc.sms.common.entity.sms.Route;

import java.util.List;

public class RouteSyncEvent extends DataSyncEvent<List<Route>> {

    private static final long serialVersionUID = -501657066268464154L;

    public RouteSyncEvent(DataSyncOperateTypeEnum operateType, List<Route> Routes, String originService, String destinationService) {
        super(new DataSync<>(operateType, Routes), originService, destinationService);
    }
}
  • 继承的抽象事件类
/**
 * 数据同步通知事件,作为一般通用事件使用,如需要特殊处理建议新增事件
 */
public abstract class DataSyncEvent<T> extends RemoteApplicationEvent {

    /**
     * 事件数据
     */
    private DataSync<T> dataSync;

    public DataSync<T> getDataSync() {
        return dataSync;
    }

    public void setDataSync(DataSync<T> dataSync) {
        this.dataSync = dataSync;
    }

    /**
     * 基础构造器
     *
     * @param source             引发事件的原始数据
     * @param originService      引发事件的原始服务
     * @param destinationService 事件的目标服务
     */
    public DataSyncEvent(DataSync<T> source, String originService, String destinationService) {
        super(source, originService, destinationService);
        this.dataSync = source;
    }

    /**
     * 事件的日志打印,会在监听器监听到事件时输出打印
     * 结果尽可能不要有换行,保证日志输出在一行内
     * 该方法可以在子类中重写
     *
     * @return 日志
     */
    public String logPrint() {
        return String.format("{\"originService\":\"%s\",\"destinationService\":\"%s\",\"id\":\"%s\",\"dataSync\":%s,\"timestamp\":\"%s\"}", this.getId(), this.getOriginService(), this.getDestinationService(), Objects.nonNull(this.dataSync) ? this.dataSync.toString() : "null", this.getTimestamp());
    }

    /**
     * 数据同步的原始数据封装
     */
    public static class DataSync<T> implements Serializable {
        private DataSyncOperateTypeEnum operateType;
        private T data;

        public DataSync() {
        }

        public DataSync(DataSyncOperateTypeEnum operateType, T data) {
            this.operateType = operateType;
            this.data = data;
        }

        public DataSyncOperateTypeEnum getOperateType() {
            return operateType;
        }

        public T getData() {
            return data;
        }

        @Override
        public String toString() {
            return "{\"operateType\":" +
                    operateType
                    + ",\"data\":" +
                    data
                    + "}";
        }
    }
}

使用bus

  • 引用注入bus应用的接口远程调用

定义bus远程调用

@FeignClient(value="sms-bus", fallbackFactory = DataSyncNotifyEventServiceFallbackFactory.class)
public interface DataSyncNotifyEventService {

    /**
     * 发布数据同步通知事件
     * destination 参数被删除,不需要指定服务
     *
     * @param eventEnum   事件枚举,可通过枚举找到对应的事件类
     * @param operateType 操作类型枚举
     * @param obj         需要处理的消息
     * @return 发布结果
     */
    @PostMapping("/default/publish/{eventEnum}/{operateType}")
    Result publishDataSyncNotifyEvent(@PathVariable("eventEnum") DataSyncEventEnum eventEnum,
                                      @PathVariable("operateType") DataSyncOperateTypeEnum operateType,
                                      @RequestBody Object obj,
                                      @RequestParam("destination") String destination);
}
  • 注入使用
    在这里插入图片描述

A应用数据更新后通过bus数据同步给B应用

  • 在A应用的业务层写以下代码
 try {
                result = dataSyncNotifyEventService.publishDataSyncNotifyEvent(DataSyncEventEnum.ROUTE_SYN,
                        DataSyncOperateTypeEnum.ADD,
                        new ArrayList<Route>() {{
                            Route r = new Route();
                            r.setCreateTime(date);
                            add(r);
                        }}, ServiceEnum.SMS_RULES.serviceName);
                log.info("新增路由调用通知同步所有服务 result:{}", result);
            } catch (Exception e) {
                log.error("同步异常 {}", result, e);
            }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用CUDA过程中出现异常

使用&#xff1a;yolo detect train dataSKU-110K.yaml modelyolov8n.pt epochs100 imgsz640 device0,1 出现错误 UserWarning: CUDA initialization: CUDA unknown error - this may be due to an incorrectly set up e nvironment, e.g. changing env variable CUDA_VISIB…

ATM和AMS启动流程

AMS 即 ActivityManagerService&#xff0c;负责 Activy、Service、Broadcast、ContentProvider 四大组件的生命周期管理。本文主要介绍 AMS 的启动流程和初始化过程。AMS 在初始化的过程中&#xff0c;也伴随着了ATMS&#xff08;ActivityTaskManagerService&#xff09;的初始…

QT使用QFileSystemModel实现的文件资源管理器(开源)

文章目录 效果图现实的功能总体框架功能介绍视图双击进入处理复制与剪切粘贴重命名&#xff0c;新建显示文件详细信息文件路径导航栏 总结 效果图 现实的功能 支持文件/文件夹复制&#xff0c;粘贴&#xff0c;剪切&#xff0c;删除&#xff0c;重命名的基本操作支持打开图片&…

一键部署私有化的思维导图SimpleMindMap

简介 SimpleMindMap 是一个可私有部署的web思维导图工具。它提供了丰富的功能和特性&#xff0c;包含插件化架构、多种结构类型&#xff08;逻辑结构图、思维导图、组织结构图等&#xff09;、节点内容支持文本、图片、图标、超链接等&#xff0c;支持拖拽、导入导出功能、快捷…

windows消息循环之手撸一个Win32窗口程序

Windows消息循环&#xff08;Windows Message Loop&#xff09; 在Windows操作系统中&#xff0c;一个程序通过不断地接收和处理消息来保持活动状态的一种机制。在Windows编程中&#xff0c;消息循环是处理用户输入、操作系统事件和其他消息的关键部分。 在Windows应用程序中…

join | join_any | join_none之间的区别

文章目录 前言一、join/join_any/join_none之间的区别总结 前言 本文主要记录一下&#xff0c;与fork想匹配的三个选项&#xff0c;join/join_any/join_none之间的区别。 一、join/join_any/join_none之间的区别 join&#xff0c;等到所有的子进程全部结束&#xff0c;才能继…

软件测试|Python自动化测试实现的思路

Python自动化测试常用于Web应用、移动应用、桌面应用等的测试 Python自动化实现思路通常分为以下几步&#xff1a; 1. 确定自动化测试的范围和目标&#xff1a; 首先需要明确需要进行自动化测试的范围和目标&#xff0c;包括测试场景、测试用例、测试数据等。 2. 选择自动化…

【代码随想录-链表】移除链表元素

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

shell脚本——条件语句

目录 一、条件语句 1、test命令测试条件表达式 2、整数数值比较 3、字符串比较 4、逻辑测试&#xff08;短路运算&#xff09; 5、双中括号 二、if语句 1、 分支结构 1.1 单分支结果 1.2 双分支 1.3 多分支 2、case 一、条件语句 条件测试&#xff1a;判断某需求是…

《Linux C编程实战》笔记:管道

从这节开始涉及进程间的通信&#xff0c;本节是管道。 管道是一种两个进程间进行单向通信的机制。因为管道传递数据的单向性&#xff0c;管道又称之为半双工管道。。管道的这一特点决定了其使用的局限性。 数据只能由一个进程刘翔另一个进程&#xff1b;如果要进行全双工通信…

快速掌握PHP:用这个网站,让学习变得简单有趣!

介绍&#xff1a;PHP是一种广泛使用的开源服务器端脚本语言&#xff0c;特别适合Web开发。 PHP&#xff0c;全称为Hypertext Preprocessor&#xff0c;即超文本预处理器&#xff0c;是一种嵌入在HTML中的服务器端脚本语言。它主要用于管理动态内容和数据库交互&#xff0c;使得…

双非本科准备秋招(9.3)—— JVM2

学这个JVM还是挺抽象的&#xff0c;不理解的东西我尽量记忆了&#xff0c;毕竟刚接触两天&#xff0c;也没遇到过实际应用场景&#xff0c;所以学起来还是挺费劲的&#xff0c;明天再补完垃圾回收这块的知识点。U•ェ•*U 先补一下JVM运行时的栈帧结构。 线程调用一个方法的执…

【并发编程】volatile原理

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;并发编程⛺️稳重求进&#xff0c;晒太阳 volatile原理实现是内存屏障&#xff0c;Memory Barrier 对volatile变量的写指令后会加入写屏障。对volatile变量的读指令前会加入读屏障 如何保…

Spring - 基本用法参考

Spring 官方文档 Spring容器启动流程&#xff08;源码解读&#xff09; BeanFactoryPostProcessor vs BeanPostProcessor vs BeanDefinitionRegistryPostProcessor&#xff1a; From java doc&#xff1a; BeanFactoryPostProcessor may interact with and modify bean defin…

网工内推 | 申通快递急招网安、测试工程师,包食宿,30k*13薪

01 申通快递 招聘岗位&#xff1a;信息安全工程师 职责描述&#xff1a; 1、 负责集团数据安全风险的识别、协同、跟踪、改进优化及事后评估&#xff1b; 2、 负责集团数据安全专项风险的治理及系统上线前的数据安全评审&#xff1b; 3、 负责集团信息安全、合规等方面制度的编…

限时回归!!!3D版《空洞骑士》!!!

空洞骑士是一款基于横板平台跳跃的传统风格2D动作冒险游戏。庞大的游戏世界交错相通&#xff0c;玩家控制小虫子去探索幽深黑暗的洞穴&#xff0c;成为了一代人茶余饭后的惦念&#xff0c;深受广大玩家们的喜爱。 这类平台跳跃游戏一般是游戏开发初学者以及独立游戏开发者们比…

React一学就会(7): 细说redux及其应用

不知不觉一个星期结束了&#xff0c;很快就要过年了&#xff0c;中间休息了两天&#xff0c;小孩生病&#xff0c;我也有点感冒了&#xff0c;还好&#xff0c;我的这个 React 基础教学课程也基本结束了。大家有不明白的可以留言问我&#xff0c;我一定竭尽所能的帮助你。后面几…

D3703F——应用于音响系统的静音检测电路 当音响系统在放音或快进 / 退时进行静音检测,输出控制信号。

D3703F 是 一 块 汽 车 音 响 静 音 检 测 电 路 。 用 于 音 响 系 统 检 测 在 放 音 或 快 进 / 退 时 进 行 静 音 检 测 。 D3703F 的 的 电 压 范 围 &#xff1a; 3.2V &#xff5e; 16V &#xff0c; 信 号 检 测 和 静 音 时 间 可 通 过 外 围 电 阻 、 电 容 来 …

中小型企业知识库建设的秘诀来啦,赶紧收藏起来

知识库是企业的智慧宝库&#xff0c;其中的信息和知识的整合&#xff0c;可以极大地提高工作效率和团队协作能力。尤其对中小企业来说&#xff0c;知识库的建设更是关系企业未来发展的重要因素。那么&#xff0c;怎样有效地构建高效的知识库系统呢&#xff1f;下面这些秘诀值得…

Arthas的使用

1. 简介 官网 线上debug神器&#xff0c;就不过多介绍 2. 环境搭建 win11环境 ,jdk11 2.1 安装 下载地址 2.2 启动 cmd java -jar arthas-boot.jar启动之后会自动检测启动的java服务 1~4 &#xff0c;springboot是启动类名&#xff0c;所以我选择了3 3. 常用操作 3.…