当前位置: 首页 > news >正文

创建延时队列、springboot配置多个rabbitmq

创建延时队列

queue.file_delay_destroy
x-dead-letter-exchange:	exchange.file_delay_destroy
x-message-ttl:	259200000
259200000为3天,1000为1秒

在这里插入图片描述

创建普通队列

queue.file_destroy

创建普通交换机

exchange.file_delay_destroy

type选择fanout
在这里插入图片描述

交换机绑定普通队列

(图中已经绑定,红框为绑定过程)
在这里插入图片描述

普通队列绑定交换机

(图中已经绑定,红框为绑定过程)
在这里插入图片描述

延时队列

springboot配置多个rabbitmq

延时队列时间到之后,将消息发送给queue.file_destroy,执行删除文件操作

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
@EqualsAndHashCode
@Data
public class MQMessage implements Serializable {private JSONObject msg;private String messageId;   //存储消息发送的唯一标识
}
import com.sxqx.entity.MQMessage;public interface MQMessageSender {/**** @param queue 消息队列名称* @param msg 消息*/void send(String queue, MQMessage msg);
}

RabbitConfig配置类

import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;@Configuration
public class RabbitConfig {@Primary@Bean(name="mq1ConnectionFactory")public ConnectionFactory mq1ConnectionFactory(@Value("${spring.rabbitmq.mq1.host}") String host,@Value("${spring.rabbitmq.mq1.port}") int port,@Value("${spring.rabbitmq.mq1.username}") String username,@Value("${spring.rabbitmq.mq1.password}") String password,@Value("${spring.rabbitmq.mq1.virtual-host}") String virtualHost){CachingConnectionFactory connectionFactory = new CachingConnectionFactory();connectionFactory.setHost(host);connectionFactory.setPort(port);connectionFactory.setUsername(username);connectionFactory.setPassword(password);connectionFactory.setVirtualHost(virtualHost);connectionFactory.setPublisherConfirms(true);connectionFactory.setPublisherReturns(true);return connectionFactory;}@Bean(name="mq2ConnectionFactory")public ConnectionFactory mq2ConnectionFactory(@Value("${spring.rabbitmq.mq2.host}") String host,@Value("${spring.rabbitmq.mq2.port}") int port,@Value("${spring.rabbitmq.mq2.username}") String username,@Value("${spring.rabbitmq.mq2.password}") String password,@Value("${spring.rabbitmq.mq2.virtual-host}") String virtualHost){CachingConnectionFactory connectionFactory = new CachingConnectionFactory();connectionFactory.setHost(host);connectionFactory.setPort(port);connectionFactory.setUsername(username);connectionFactory.setPassword(password);connectionFactory.setVirtualHost(virtualHost);connectionFactory.setPublisherConfirms(true);connectionFactory.setPublisherReturns(true);return connectionFactory;}@Primary@Bean(name="mq1RabbitTemplate")public RabbitTemplate mq1RabbitTemplate(@Qualifier("mq1ConnectionFactory") ConnectionFactory connectionFactory){RabbitTemplate mq1RabbitTemplate = new RabbitTemplate(connectionFactory);mq1RabbitTemplate.setMessageConverter(jsonMessageConverter());return mq1RabbitTemplate;}@Bean(name="mq2RabbitTemplate")public RabbitTemplate mq2RabbitTemplate(@Qualifier("mq2ConnectionFactory") ConnectionFactory connectionFactory){RabbitTemplate mq2RabbitTemplate = new RabbitTemplate(connectionFactory);mq2RabbitTemplate.setMessageConverter(jsonMessageConverter());return mq2RabbitTemplate;}@Beanpublic Jackson2JsonMessageConverter jsonMessageConverter() {return new Jackson2JsonMessageConverter();}@Bean(name = "mq1Factory")@Primarypublic SimpleRabbitListenerContainerFactory mq1Factory(SimpleRabbitListenerContainerFactoryConfigurer configurer,@Qualifier("mq1ConnectionFactory") ConnectionFactory connectionFactory) {SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();configurer.configure(factory, connectionFactory);return factory;}@Bean(name = "mq2Factory")public SimpleRabbitListenerContainerFactory mq2Factory(SimpleRabbitListenerContainerFactoryConfigurer configurer,@Qualifier("mq2ConnectionFactory") ConnectionFactory connectionFactory) {SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();configurer.configure(factory, connectionFactory);return factory;}
}

mq1

@Component
public class RabbitMQ1MessageSender  implements MQMessageSender, RabbitTemplate.ConfirmCallback{@Resource(name = "mq1RabbitTemplate")private RabbitTemplate mq1RabbitTemplate;Log log = LogFactory.getLog(RabbitMQ1MessageSender.class);@Autowiredpublic RabbitMQ1MessageSender() {}@PostConstructpublic void init(){mq1RabbitTemplate.setConfirmCallback(this);}@Overridepublic void confirm(CorrelationData correlationData, boolean ack, String cause) {if(!ack){log.error("消息接收失败" + cause);// 我们这里要做一些消息补发的措施System.out.println("id="+correlationData.getId());}}@Overridepublic void send(String routingKey, MQMessage msg) {String jsonString = JsonConverter.bean2Json(msg);if (jsonString != null) {mq1RabbitTemplate.convertAndSend(routingKey, jsonString);}}
}

mq2

import com.sxqx.entity.MQMessage;
import com.sxqx.utils.dataConverter.JsonConverter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import javax.annotation.Resource;@Component
public class RabbitMQ2MessageSender implements MQMessageSender, RabbitTemplate.ConfirmCallback{@Resource(name = "mq2RabbitTemplate")private RabbitTemplate mq2RabbitTemplate;Log log = LogFactory.getLog(RabbitMQ2MessageSender.class);@Autowiredpublic RabbitMQ2MessageSender() {}@PostConstructpublic void init(){mq2RabbitTemplate.setConfirmCallback(this);}@Overridepublic void confirm(CorrelationData correlationData, boolean ack, String cause) {if(!ack){log.error("消息接收失败" + cause);// 我们这里要做一些消息补发的措施System.out.println("id="+correlationData.getId());}}@Overridepublic void send(String routingKey, MQMessage msg) {String jsonString = JsonConverter.bean2Json(msg);if (jsonString != null) {mq2RabbitTemplate.convertAndSend(routingKey, jsonString);}}
}

application-prod.yaml

spring:rabbitmq:mq1:username: guestpassword: guesthost: mq1_ipport: 5672virtual-host: /publisher-returns: truepublisher-confirm-type: simplelistener:simple:acknowledge-mode: auto # 手动应答prefetch: 10 #每次从队列中取一个,轮询分发,默认是公平分发retry:max-attempts: 5 # 重试次数enabled: true # 开启重试concurrency: 5max-concurrency: 10mq2:username: guestpassword: guesthost: mq2_ipport: 5672virtual-host: /publisher-returns: truepublisher-confirm-type: simplelistener:simple:acknowledge-mode: auto # 手动应答prefetch: 10 #每次从队列中取一个,轮询分发,默认是公平分发retry:max-attempts: 5 # 重试次数enabled: true # 开启重试concurrency: 5max-concurrency: 10

mq1消费端,发消息给mq2

@Component
public class SyncWeatherLivePicMessageReceiver  implements IMessageReceiver {private final IWeatherLivePicMapper weatherLivePicMapper;private final RabbitMQ2MessageSender rabbitMQ2MessageSender;@Autowiredpublic SyncWeatherLivePicMessageReceiver(IWeatherLivePicMapper weatherLivePicMapper,RabbitMQ2MessageSender rabbitMQ2MessageSender) {this.weatherLivePicMapper = weatherLivePicMapper;this.rabbitMQ2MessageSender = rabbitMQ2MessageSender;}Log log = LogFactory.getLog(SyncWeatherLivePicMessageReceiver.class);private FtpHelper ftpHelperIns1;private FtpHelper ftpHelperIns2;private FTPFileFilter ftpFileFilter;@RabbitListener(queuesToDeclare = {@Queue(name = "sxqxgzbgxw_weather_live_pic")})@RabbitHandler@Overridepublic void onMessageReceived(String mqMessageString) {JsonNode jsonNode = JsonConverter.jsonString2JsonNode(mqMessageString);JsonNode msg = jsonNode.findValue("msg");JsonNode JsonNodeParams = msg.findValue("params");Map<String, Object> params = JsonConverter.jsonNode2HashMap(JsonNodeParams);if (params.size() > 0) {String times = params.get("times").toString();String serverFrom = params.get("serverFrom").toString();......// 清除数据MQMessage mqMessage = new MQMessage();JSONObject jsonObject = new JSONObject();jsonObject.put("filePath", "/data/static/dataSharingStatic/weatherlive/colorFigure/png/610000/610000/"+ times);mqMessage.setMsg(jsonObject);rabbitMQ2MessageSender.send("queue.file_delay_destroy", mqMessage);// 清除DB记录MQMessage mqMessage2 = new MQMessage();JSONObject jsonObject2 = new JSONObject();jsonObject2.put("tableName", "WEATHER_LIVE_PIC");jsonObject2.put("picUrl", "http://外网ip/dataSharingStatic/weatherlive/colorFigure/png/610000/610000/"+ times +"/"+ type + "/" + "gjzjqyz/"+ fileNameFrom);mqMessage2.setMsg(jsonObject);rabbitMQ2MessageSender.send("queue.db_delay_destroy", mqMessage2);                }}
}

mq2消费端用于递归删除文件

import com.fasterxml.jackson.databind.JsonNode;
import com.sxqx.listener.IMessageReceiver;
import com.sxqx.utils.dataConverter.JsonConverter;
import com.sxqx.utils.file.FileHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;import java.io.File;@Component
public class FileDestroyMessageReceiver implements IMessageReceiver {Log log = LogFactory.getLog(FileDestroyMessageReceiver.class);@RabbitListener(queuesToDeclare = {@Queue(name = "queue.file_destroy")})@RabbitHandler@Overridepublic void onMessageReceived(String mqMessageString) {JsonNode jsonNode = JsonConverter.jsonString2JsonNode(mqMessageString);JsonNode msg = jsonNode.findValue("msg");String filePath = msg.findValue("filePath").asText();if (filePath.contains("/data/static/dataSharingStatic/weatherlive/colorFigure/png/610000/610000")) {File file = new File(filePath);if (file.exists()) {FileHelper.deleteFile(file);}} else {log.info("有人想删除设定之外的文件");log.info(filePath);}}
}

FileHelper工具类递归删除文件或文件夹

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;public class FileHelper {/*** 递归删除文件或文件夹* @param directory*/public static void deleteFile(File directory) {if (!directory.exists()) {return;}File[] files = directory.listFiles();if (files!=null) {//如果包含文件进行删除操作for (File value : files) {if (value.isFile()) {//删除子文件value.delete();} else if (value.isDirectory()) {//通过递归的方法找到子目录的文件deleteFile(value);}value.delete();//删除子目录}}directory.delete();}
}

mq2消费端用于删除数据库数据

import com.fasterxml.jackson.databind.JsonNode;
import com.sxqx.listener.IMessageReceiver;
import com.sxqx.mapper.remote.xugugzb.weatherlivepic.IWeatherLivePicMapper;
import com.sxqx.utils.dataConverter.JsonConverter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.util.Objects;@Component
public class DBDestroyMessageReceiver implements IMessageReceiver {private final IWeatherLivePicMapper weatherLivePicMapper;@Autowiredpublic DBDestroyMessageReceiver(IWeatherLivePicMapper weatherLivePicMapper){this.weatherLivePicMapper = weatherLivePicMapper;}Log log = LogFactory.getLog(DBDestroyMessageReceiver.class);@RabbitListener(queuesToDeclare = {@Queue(name = "queue.db_destroy")})@RabbitHandler@Overridepublic void onMessageReceived(String mqMessageString) {JsonNode jsonNode = JsonConverter.jsonString2JsonNode(mqMessageString);JsonNode msg = jsonNode.findValue("msg");String tableName = msg.findValue("tableName").asText();String picUrl = msg.findValue("picUrl").asText();if (picUrl.contains("/dataSharingStatic/weatherlive/colorFigure/png/610000/610000/")) {if (Objects.equals("WEATHER_LIVE_PIC",tableName)) {weatherLivePicMapper.deleteWeatherLivePic(picUrl);}} else {log.info("有人想删除设定之外的数据");log.info(picUrl);}}
}

nginx.conf

上传静态资源至linux path,配置nginx.conf,使浏览器可以直接访问静态资源

server {listen       80;server_name  60.204.202.112;add_header   Cache-Control no-store;charset	     utf-8;location / {root   /mnt/sxqxgxw-gzb-front/dist/;try_files $uri $uri/ /index.html;index  index.html index.htm;}#访问/dataSharingStatic时,相当于访问/data/static/dataSharingStatic路径下资源location /dataSharingStatic {root   /data/static;autoindex   on;add_header  Access-Control-Allow-Origin *;add_header  Access-Control-Allow-Headers X-Requestd-With;add_header  Access-Control-Allow-Methods GET,POST,OPTIONS;}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}location /api/ {proxy_pass    http://60.204.202.112:8896;rewrite	  ^/api/(.*)$ /$1 break;add_header    Access-Control-Allow-Origin *;add_header    Access-Control-Allow-Headers X-Requestd-With;add_header	  Access-Control-Allow-Methods GET,POST,OPTIONS;}}

相关文章:

创建延时队列、springboot配置多个rabbitmq

创建延时队列 queue.file_delay_destroy x-dead-letter-exchange: exchange.file_delay_destroy x-message-ttl: 259200000 259200000为3天,1000为1秒创建普通队列 queue.file_destroy创建普通交换机 exchange.file_delay_destroytype选择fanout 交换机绑定普通队列 (图中…...

在kaggle中用GPU使用CGAN生成指定mnist手写数字

文章目录 1项目介绍2参考文章3代码的实现过程及对代码的详细解析独热编码定义生成器定义判别器打印我们的引导信息模型训练迭代过程中生成的图片损失函数的变化 4总结5 模型相关的文件 1项目介绍 在GAN的基础上进行有条件的引导生成图片cgan 2参考文章 GAN实战之Pytorch 使用…...

【NI USRP】哪些 USRP 设备支持全双工,哪些支持半双工?

译者 东枫电子科技 设备构成 NI USRPEttus USRPUSRP-2900B200USRP-2901B210USRP-2920N210 WBXUSRP-2921N210 XCVR 2450USRP-2922N210 SBXUSRP-2930N210 WBX GPSDOUSRP-2932N210 SBX GPSDOUSRP-2940RX310 WBX (x2)USRP-2942RX310 SBX (x2)USRP-2943RX310 CBX (x2)U…...

不拼花哨,只拼实用:unittest指南,干货为王!

Python为开发者提供了内置的单元测试框架 unittest&#xff0c;它是一种强大的工具&#xff0c;能够有效地编写和执行单元测试。unittest 提供了完整的测试结构&#xff0c;支持自动化测试的执行&#xff0c;能够对测试用例进行组织&#xff0c;并且提供了丰富的断言方法。最终…...

mysql 获取json数组中某个字段根据下标

MySQL获取JSON数组中某个字段根据下标 在MySQL中&#xff0c;JSON数据类型可以方便地存储、操作和查询包含复杂结构的数据。当我们需要从JSON数组中获取某个字段时&#xff0c;可以使用MySQL的JSON函数来实现。 1. JSON数据类型简介 JSON&#xff08;JavaScript Object Nota…...

深入理解Redis缓存穿透、击穿、雪崩及解决方案

深入理解Redis缓存穿透、击穿、雪崩及解决方案 一、简介Redis 简介缓存作用与优化 二、缓存问题的分类缓存穿透缓存击穿缓存雪崩 三、缓存穿透的解决方案布隆过滤器缓存空对象接口层校验 四、缓存击穿的解决方案互斥锁热点数据提前加载 五、缓存雪崩的解决方案增加缓存容错能力…...

java八股文面试[java基础]——字节码

字节码技术应用 字节码技术的应用场景包括但不限于AOP&#xff0c;动态生成代码&#xff0c;接下来讲一下字节码技术相关的第三方类库&#xff0c;第三方框架的讲解是为了帮助大家了解字节码技术的应用方向&#xff0c;文档并没有对框架机制进行详细分析&#xff0c;有兴趣的可…...

新能源汽车技术的最新进展和未来趋势

文章目录 电池技术的进步智能驾驶与自动驾驶技术充电基础设施建设新能源汽车共享和智能交通未来趋势展望结论 &#x1f389;欢迎来到AIGC人工智能专栏~探索新能源汽车技术的最新进展和未来趋势 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a;IT陈寒的博客…...

知虾shopee数据分析工具:shopee出单的商机利器

当今数字化时代&#xff0c;数据已经成为商业成功的关键要素之一。而Shopee作为东南亚最大的电商平台之一&#xff0c;其强大的数据分析工具正为商家提供了宝贵的市场洞察和决策支持。本文将深入探讨Shopee数据分析工具如何帮助商家抓住商机并取得成功。 洞察消费者需求&#x…...

python——ydata-profiling介绍与使用

ydata-profiling介绍与使用 ydata-profiling的作用ydata-profiling的安装与简单使用ydata-profiling的结果结构 ydata-profiling的实际应用场景1. 数据集比较2. 时间序列报告3. 对大型数据集进行概要分析4. 处理敏感数据5. 自定义报告的外观 ydata-profiling的作用 ydata-prof…...

(纯c)数据结构之------>链表(详解)

目录 一. 链表的定义 1.链表的结构. 2.为啥要存在链表及链表的优势. 二. 无头单向链表的常用接口 1.头插\尾插 2.头删\尾删 3.销毁链表/打印链表 4.在pos位置后插入一个值 5.消除pos位置后的值 6.查找链表中的值并且返回它的地址 7.创建一个动态开辟的结点 三.顺序表与链表…...

postman接口自动化测试框架实战!

什么是自动化测试 把人对软件的测试行为转化为由机器执行测试行为的一种实践。 例如GUI自动化测试&#xff0c;模拟人去操作软件界面&#xff0c;把人从简单重复的劳动中解放出来。 本质是用代码去测试另一段代码&#xff0c;属于一种软件开发工作&#xff0c;已经开发完成的用…...

Apache Doris 入门教程35:多源数据目录

概述 多源数据目录&#xff08;Multi-Catalog&#xff09;功能&#xff0c;旨在能够更方便对接外部数据目录&#xff0c;以增强Doris的数据湖分析和联邦数据查询能力。 在之前的 Doris 版本中&#xff0c;用户数据只有两个层级&#xff1a;Database 和 Table。当我们需要连接…...

响应式web-PC端web与移动端web(H5)兼容适配 选型方案

背景 项目需要&#xff0c;公司已经有一套PC端web&#xff0c;需要做一套手机端浏览器可用的&#xff0c;但是又想兼容pc端&#xff0c;适配的web项目。 以下是查阅到响应布局现成的开源模版。根据自己技术栈&#xff0c;vue2,js来搜索相关的开源项目。 RuoYi 使用若依快速…...

Redis持久化之RDB解读

目录 什么是RDB 配置位置参数解读 如何使用 自动触发 手动触发 save bgsave RDBRDB持久化文件的恢复 正常恢复 恢复失败处理方法 RDB优势 RDB 缺点 redis是一个内存数据库,当redis服务器重启,获取电脑重启,数据会丢失,我们可以将redis内存中的数据持久化保存到硬盘…...

四维图新 minemap实现地图漫游效果

原理就是不断改变地图中心点&#xff0c;改变相机角度方向&#xff0c;明白这一点&#xff0c;其他地图引擎譬如cesium都可效仿&#xff0c;本人就是通过cesium的漫游实现四维图新的漫游&#xff0c;唯一不足的是转弯的时候不能丝滑转向&#xff0c;尝试过应该是四维图新引擎的…...

centos7安装MySQL8

Centos7安装MySQL8 MySQL版本&#xff1a;8.0.34 1.安装前准备 &#xff08;1&#xff09;查看是否安装mariadb [rootkb135 ~]# rpm -qa|grep mariadb &#xff08;2&#xff09;卸载mariadb并检查是否卸干净 [rootkb135 ~]# rpm -e --nodeps mariadb-libs-5.5.68-1.el7.x8…...

【IMX6ULL驱动开发学习】10.Linux I2C驱动实战:AT24C02驱动设计流程

前情回顾&#xff1a;【IMX6ULL驱动开发学习】09.Linux之I2C框架简介和驱动程序模板_阿龙还在写代码的博客-CSDN博客 目录 一、修改设备树&#xff08;设备树用来指定引脚资源&#xff09; 二、编写驱动 2.1 i2c_drv_read 2.2 i2c_drv_write 2.3 完整驱动程序 三、上机测…...

【C++】详解声明和定义

2023年8月28日&#xff0c;周一下午 研究了一个下午才彻底弄明白... 写到晚上才写完这篇博客。 目录 声明和定义的根本区别结构体的声明和定义声明结构体 定义结构体类的声明和定义函数的定义和声明声明函数 定义函数变量声明和定义声明变量定义变量 声明和定义的根本区别 …...

掌握C/C++协程编程,轻松驾驭并发编程世界

一、引言 协程的定义和背景 协程&#xff08;Coroutine&#xff09;&#xff0c;又称为微线程或者轻量级线程&#xff0c;是一种用户态的、可在单个线程中并发执行的程序组件。协程可以看作是一个更轻量级的线程&#xff0c;由程序员主动控制调度。它们拥有自己的寄存器上下文…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a;单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a;应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠标…...

MySQL 主从同步异常处理

阅读原文&#xff1a;https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主&#xff0c;遇到的这个错误&#xff1a; Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一&#xff0c;通常表示&#xff…...