RabbitMQ面试精讲 Day 4:Queue属性与消息特性

【RabbitMQ面试精讲 Day 4】Queue属性与消息特性

开篇

欢迎来到"RabbitMQ面试精讲"系列的第4天!今天我们将深入探讨RabbitMQ中Queue的属性配置与消息特性,这是理解和优化RabbitMQ使用的关键知识点。掌握这些内容不仅能帮助你在面试中展现深厚的技术功底,更能让你在实际项目中合理配置队列属性,构建高效可靠的消息系统。

在面试中,面试官通常会通过以下方式考察候选人对Queue和消息特性的理解:

  • 解释RabbitMQ队列的核心属性及其作用
  • 分析消息持久化与队列持久化的区别与联系
  • 讨论消息TTL和队列TTL的优先级关系
  • 解释死信队列的工作原理和实际应用
  • 处理消息堆积问题的策略和最佳实践

本文将系统性地解析这些关键问题,并提供生产环境中的实际应用案例,助你全面掌握RabbitMQ队列与消息特性的方方面面。

概念解析:Queue核心属性

RabbitMQ队列是消息的最终目的地,了解其核心属性对于构建可靠的消息系统至关重要。以下是队列声明时可以配置的主要属性:

属性类型描述默认值
durableboolean是否持久化队列false
exclusiveboolean是否为排他队列false
auto-deleteboolean当最后一个消费者断开后是否自动删除队列false
argumentsMap额外参数配置null

1. durable(持久化)

持久化队列会在RabbitMQ服务器重启后依然存在,而非持久化队列会被删除。注意:队列持久化并不代表消息持久化,消息持久化需要单独设置。

2. exclusive(排他性)

排他队列只能被声明它的连接使用,当连接关闭时,队列会被自动删除。适用于临时队列场景。

3. auto-delete(自动删除)

当最后一个消费者取消订阅后,队列会被自动删除。适用于临时任务队列。

4. arguments(额外参数)

常见的arguments配置包括:

参数作用示例值
x-message-ttl队列中消息的存活时间(毫秒)60000
x-expires队列空闲多久后被删除(毫秒)1800000
x-max-length队列最大消息数1000
x-max-length-bytes队列最大字节数1048576
x-dead-letter-exchange死信交换机“dlx.exchange”
x-dead-letter-routing-key死信路由键“dlx.routing”
x-max-priority队列支持的最大优先级10
x-queue-mode队列模式("lazy"为惰性队列)“lazy”

原理剖析:消息特性详解

1. 消息持久化

消息持久化需要同时满足两个条件:

  1. 队列设置为持久化(durable=true)
  2. 消息投递时设置delivery mode=2
// 创建持久化队列
channel.queueDeclare("persistent.queue", true, false, false, null);// 发送持久化消息
AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
.deliveryMode(2)  // 持久化消息
.build();
channel.basicPublish("", "persistent.queue", properties, "message".getBytes());

2. 消息TTL(Time-To-Live)

RabbitMQ支持两种TTL设置方式:

方式作用范围优先级设置方法
队列TTL对整个队列生效通过x-message-ttl参数设置
消息TTL对单个消息生效通过expiration属性设置

当消息在队列中存活时间超过TTL时,会变成死信(dead letter),可以被转发到死信队列。

// 设置队列TTL (60秒)
Map<String, Object> args = new HashMap<>();
args.put("x-message-ttl", 60000);
channel.queueDeclare("ttl.queue", true, false, false, args);// 设置消息TTL (30秒)
AMQP.BasicProperties props = new AMQP.BasicProperties.Builder()
.expiration("30000")
.build();
channel.basicPublish("", "ttl.queue", props, "message".getBytes());

3. 优先级队列

RabbitMQ支持优先级队列,需要:

  1. 设置队列的x-max-priority参数
  2. 发送消息时设置priority属性
// 创建优先级队列(支持0-10级)
Map<String, Object> args = new HashMap<>();
args.put("x-max-priority", 10);
channel.queueDeclare("priority.queue", true, false, false, args);// 发送高优先级消息
AMQP.BasicProperties highPriority = new AMQP.BasicProperties.Builder()
.priority(5)
.build();
channel.basicPublish("", "priority.queue", highPriority, "important".getBytes());

代码实现:多语言客户端示例

Java (RabbitMQ Client) 示例

import com.rabbitmq.client.*;public class QueueExample {
private final static String QUEUE_NAME = "example.queue";public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");try (Connection connection = factory.newConnection();
Channel channel = connection.createChannel()) {// 创建带有多种属性的队列
Map<String, Object> arguments = new HashMap<>();
arguments.put("x-message-ttl", 60000); // 消息TTL 60秒
arguments.put("x-max-length", 100);    // 最大100条消息
arguments.put("x-dead-letter-exchange", "dlx.exchange"); // 死信交换机channel.queueDeclare(QUEUE_NAME,
true,     // 持久化
false,    // 非排他
false,    // 非自动删除
arguments // 额外参数
);// 发送不同特性的消息
sendPersistentMessage(channel);
sendTTLMessage(channel);
sendPriorityMessage(channel);
}
}private static void sendPersistentMessage(Channel channel) throws Exception {
AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
.deliveryMode(2) // 持久化消息
.build();channel.basicPublish("", QUEUE_NAME, properties,
"Persistent Message".getBytes());
}private static void sendTTLMessage(Channel channel) throws Exception {
AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
.expiration("30000") // 30秒TTL
.build();channel.basicPublish("", QUEUE_NAME, properties,
"TTL Message".getBytes());
}private static void sendPriorityMessage(Channel channel) throws Exception {
AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
.priority(8) // 优先级8
.build();channel.basicPublish("", QUEUE_NAME, properties,
"Priority Message".getBytes());
}
}

Python (pika) 示例

import pikaconnection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()# 创建复杂队列
args = {
'x-message-ttl': 60000,          # 消息TTL 60秒
'x-max-length': 100,             # 最大100条消息
'x-dead-letter-exchange': 'dlx', # 死信交换机
'x-max-priority': 10             # 支持优先级
}
channel.queue_declare(queue='example.queue', durable=True, arguments=args)# 发送持久化消息
channel.basic_publish(
exchange='',
routing_key='example.queue',
body='Persistent Message',
properties=pika.BasicProperties(
delivery_mode=2,  # 持久化消息
))# 发送TTL消息
channel.basic_publish(
exchange='',
routing_key='example.queue',
body='TTL Message',
properties=pika.BasicProperties(
expiration='30000',  # 30秒TTL
))# 发送优先级消息
channel.basic_publish(
exchange='',
routing_key='example.queue',
body='Priority Message',
properties=pika.BasicProperties(
priority=5,  # 优先级5
))connection.close()

面试题解析

面试题1:RabbitMQ的队列持久化和消息持久化有什么区别?如何同时实现两者?

考察意图:考察候选人对RabbitMQ持久化机制的理解深度和应用能力。

结构化回答

  1. 概念区别
  • 队列持久化:队列定义在RabbitMQ重启后仍然存在
  • 消息持久化:消息内容在RabbitMQ重启后仍然存在
  1. 配置方式
  • 队列持久化:在queueDeclare时设置durable=true
  • 消息持久化:在basicPublish时设置deliveryMode=2
  1. 相互关系
  • 队列不持久化时,即使消息持久化,重启后队列和消息都会丢失
  • 队列持久化但消息不持久化,重启后队列存在但消息丢失
  • 两者都持久化才能确保消息不丢失
  1. 最佳实践
// 持久化队列
channel.queueDeclare("durable.queue", true, false, false, null);// 持久化消息
AMQP.BasicProperties props = new AMQP.BasicProperties.Builder()
.deliveryMode(2)
.build();
channel.basicPublish("", "durable.queue", props, message.getBytes());

面试题2:消息TTL和队列TTL同时设置时,哪个优先级更高?

考察意图:考察候选人对TTL机制的理解和实际应用经验。

结构化回答
RabbitMQ中TTL的优先级规则如下:

  1. 消息级TTL优先
  • 如果消息设置了expiration属性,则以此值为准
  • 否则使用队列的x-message-ttl参数值
  1. 设置方式对比
    | 设置级别 | 参数 | 影响范围 | 灵活性 |
    | — | — | — | — |
    | 队列 | x-message-ttl | 所有消息 | 统一管理 |
    | 消息 | expiration | 单个消息 | 灵活控制 |

  2. 实际应用建议

  • 需要统一过期时间的场景使用队列TTL
  • 需要差异化过期时间的场景使用消息TTL
  • 两者可以结合使用,提供默认值和特殊值
  1. 代码示例
// 队列TTL设置为60秒
Map<String, Object> args = new HashMap<>();
args.put("x-message-ttl", 60000);
channel.queueDeclare("ttl.queue", true, false, false, args);// 消息TTL设置为30秒(优先级更高)
AMQP.BasicProperties props = new AMQP.BasicProperties.Builder()
.expiration("30000")
.build();
channel.basicPublish("", "ttl.queue", props, "message".getBytes());

面试题3:如何设计一个可靠的死信队列处理系统?

考察意图:考察候选人对RabbitMQ高级特性的理解和解决实际问题的能力。

结构化回答
死信队列(DLX)是处理失败消息的重要机制,可靠设计需要考虑以下方面:

  1. 死信队列定义
  • 消息变成死信的条件:
  • 消息被拒绝(basic.reject/nack)且requeue=false
  • 消息TTL过期
  • 队列达到最大长度
  1. 核心组件
  • 死信交换机(DLX):接收死信的普通交换机
  • 死信队列:绑定到DLX的队列,存储死信
  • 死信消费者:专门处理死信的服务
  1. 实现步骤
// 1. 定义死信交换机
channel.exchangeDeclare("dlx.exchange", "direct");
channel.queueDeclare("dlx.queue", true, false, false, null);
channel.queueBind("dlx.queue", "dlx.exchange", "dlx.routing");// 2. 定义工作队列并指定DLX
Map<String, Object> args = new HashMap<>();
args.put("x-dead-letter-exchange", "dlx.exchange");
args.put("x-dead-letter-routing-key", "dlx.routing");
channel.queueDeclare("work.queue", true, false, false, args);// 3. 消费者处理逻辑
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
try {
processMessage(delivery.getBody());
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
} catch (Exception e) {
// 处理失败,发送到死信队列
channel.basicNack(delivery.getEnvelope().getDeliveryTag(), false, false);
}
};
channel.basicConsume("work.queue", false, deliverCallback, consumerTag -> {});
  1. 增强可靠性
  • 监控死信队列长度
  • 实现死信消息的重试机制
  • 记录死信原因和上下文信息
  • 设置死信消息的TTL防止无限堆积

实践案例

案例1:电商订单超时取消系统

利用消息TTL和死信队列实现订单30分钟未支付自动取消功能。

public class OrderTimeoutSystem {
private static final String ORDER_EXCHANGE = "order.exchange";
private static final String ORDER_QUEUE = "order.queue";
private static final String DLX_EXCHANGE = "order.dlx";
private static final String DLX_QUEUE = "order.dlx.queue";public void init() throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();// 定义死信交换机和队列
channel.exchangeDeclare(DLX_EXCHANGE, "direct");
channel.queueDeclare(DLX_QUEUE, true, false, false, null);
channel.queueBind(DLX_QUEUE, DLX_EXCHANGE, "");// 定义订单队列并配置死信
Map<String, Object> args = new HashMap<>();
args.put("x-dead-letter-exchange", DLX_EXCHANGE);
args.put("x-message-ttl", 1800000); // 30分钟TTL
channel.queueDeclare(ORDER_QUEUE, true, false, false, args);// 定义订单交换机
channel.exchangeDeclare(ORDER_EXCHANGE, "direct");
channel.queueBind(ORDER_QUEUE, ORDER_EXCHANGE, "");// 死信消费者处理超时订单
DeliverCallback dlxCallback = (consumerTag, delivery) -> {
String orderId = new String(delivery.getBody());
cancelOrder(orderId); // 取消订单业务逻辑
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
};
channel.basicConsume(DLX_QUEUE, false, dlxCallback, consumerTag -> {});
}public void placeOrder(String orderId) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try (Connection connection = factory.newConnection();
Channel channel = connection.createChannel()) {
channel.basicPublish(ORDER_EXCHANGE, "", null, orderId.getBytes());
}
}private void cancelOrder(String orderId) {
// 实现订单取消逻辑
System.out.println("Canceling order: " + orderId);
}
}

案例2:优先级任务处理系统

实现支持高优先级任务插队的后台任务系统。

import pikaclass PriorityTaskSystem:
def __init__(self):
self.connection = pika.BlockingConnection(
pika.ConnectionParameters('localhost'))
self.channel = self.connection.channel()# 创建优先级队列
args = {'x-max-priority': 10}
self.channel.queue_declare(queue='task.queue', durable=True, arguments=args)def add_task(self, task, priority=0):
properties = pika.BasicProperties(
priority=priority,
delivery_mode=2  # 持久化消息
)
self.channel.basic_publish(
exchange='',
routing_key='task.queue',
body=task,
properties=properties)def process_tasks(self):
def callback(ch, method, properties, body):
print(f"Processing task: {body}, priority: {properties.priority}")
# 模拟任务处理
time.sleep(1)
ch.basic_ack(delivery_tag=method.delivery_tag)# 设置QoS,每次只处理一个任务
self.channel.basic_qos(prefetch_count=1)
self.channel.basic_consume(
queue='task.queue',
on_message_callback=callback)print('Waiting for tasks...')
self.channel.start_consuming()# 使用示例
if __name__ == "__main__":
system = PriorityTaskSystem()
# 添加普通任务
system.add_task("Normal task 1")
system.add_task("Normal task 2")
# 添加高优先级任务
system.add_task("Urgent task", priority=9)
system.process_tasks()

技术对比:普通队列 vs 惰性队列

RabbitMQ 3.6.0引入了惰性队列(Lazy Queue)的概念,与传统队列在工作方式上有显著差异:

特性普通队列惰性队列
内存使用尽可能将消息保存在内存尽可能将消息保存在磁盘
吞吐量稍低
适用场景消息处理速度快,内存充足消息堆积严重,内存有限
配置方式默认模式x-queue-mode=lazy
消息堆积容易导致内存溢出更适合处理堆积
启动速度快(消息在内存)慢(需要从磁盘加载)

惰性队列适合以下场景:

  • 消费者可能长时间离线
  • 需要处理突发的大量消息
  • 系统内存资源有限
// 创建惰性队列
Map<String, Object> args = new HashMap<>();
args.put("x-queue-mode", "lazy");
channel.queueDeclare("lazy.queue", true, false, false, args);

面试官喜欢的回答要点

  1. 全面理解队列属性
  • 清楚解释durable、exclusive、auto-delete的区别
  • 能列举并说明常见arguments参数的作用
  1. 深入消息特性
  • 区分消息持久化和队列持久化的关系和区别
  • 理解TTL的两种设置方式及优先级
  1. 高级特性应用
  • 能设计完整的死信队列处理系统
  • 了解优先级队列和惰性队列的使用场景
  1. 实际问题解决
  • 针对消息堆积、顺序处理等问题提供解决方案
  • 讨论不同场景下的队列配置策略
  1. 性能考量
  • 分析不同配置对性能的影响
  • 理解内存与磁盘使用的权衡

总结与预告

今天我们深入学习了RabbitMQ的Queue属性与消息特性,包括:

  • 队列的核心属性及其作用
  • 消息持久化与TTL机制
  • 死信队列的实现原理
  • 优先级队列和惰性队列
  • 多语言客户端代码示例
  • 高频面试题解析
  • 生产环境实践案例

明日预告:Day 5将探讨"Virtual Host与权限控制",我们将深入分析:

  • Virtual Host的概念和作用
  • RabbitMQ权限系统详解
  • 用户角色与权限配置
  • 多租户系统设计实践
  • 安全最佳实践

进阶学习资源

  1. RabbitMQ官方文档 - Queues
  2. RabbitMQ in Depth - 队列特性章节
  3. RabbitMQ最佳实践指南

希望本文能帮助你在面试中自信应对RabbitMQ队列与消息特性的相关问题,并在实际开发中合理运用这些特性构建可靠的消息系统。如有任何疑问,欢迎在评论区留言讨论!

文章标签:RabbitMQ,消息队列,队列属性,消息特性,面试技巧,后端开发,分布式系统

文章简述:本文是"RabbitMQ面试精讲"系列第4篇,全面解析RabbitMQ队列属性与消息特性。内容涵盖队列持久化、消息TTL、死信队列、优先级队列等核心概念,提供Java/Python多语言代码示例,深入分析3个高频面试题及电商订单超时、优先级任务处理等实践案例。针对RabbitMQ消息特性的常见面试难点,如持久化机制、TTL优先级、死信队列设计等,提供结构化回答模板和技术对比,帮助开发者深入理解RabbitMQ队列工作原理,提升面试表现和工程实践能力。

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

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

相关文章

uniapp vue3 vite项目使用微信云开发(云函数)

1、在根目录新建文件夹 cloudfunctions2、配置 manifest.json在项目根目录的 manifest.json 文件中&#xff0c;找到微信小程序配置部分&#xff0c;添加 cloudfunctionRoot 字段&#xff0c;指向你的云函数目录&#xff1a;{"mp-weixin": {"cloudfunctionRoot&…

AK视频下载工具:免费高效,多平台支持

近期小编又发现了一款更强大的新神器——AK视频下载&#xff08;电脑版&#xff09;&#xff0c;一起来了解下吧~ 软件亮点 完全免费&#xff0c;无需安装&#xff0c;操作便捷&#xff0c;直接打开即可使用。 支持多平台视频下载&#xff0c;包括抖音、B站、小红书、快手等主…

7月21日星期一今日早报简报微语报早读

7月21日星期一&#xff0c;农历六月廿七&#xff0c;早报#微语早读。1、广东佛山累计报告基孔肯雅热确诊病例1873例&#xff0c;均为轻症&#xff1b;2、祝贺&#xff01;石宇奇夺得日本羽毛球公开赛男单冠军&#xff1b;3、中国和匈牙利顺利完成引渡条约谈判&#xff1b;4、科…

基于Milvus Lite的轻量级向量数据库实战指南

一、为什么选择Milvus Lite&#xff1f; 在人工智能和语义搜索应用中&#xff0c;高效的向量检索是核心需求。相比需要部署Docker的完整版Milvus&#xff0c;Milvus Lite提供&#xff1a; 零依赖&#xff1a;纯Python实现&#xff0c;无需安装Docker或外部组件 开箱即用&…

深度学习时代下的社交媒体情感分析:方法、工具与未来挑战

摘要&#xff1a;基于Yue等学者2019年发表的权威综述&#xff0c;本文系统总结情感分析的技术框架、实战资源与前沿方向&#xff0c;附Python代码示例。 一、情感分析为何重要&#xff1f; 情感分析&#xff08;Sentiment Analysis&#xff09;旨在从文本中提取主观态度&…

Spring Boot 3.0新特性全面解析与实战应用

Spring Boot 3.0新特性全面解析与实战应用 引言 Spring Boot 3.0作为Spring生态系统的一个重要里程碑&#xff0c;带来了众多令人兴奋的新特性和改进。本文将深入解析Spring Boot 3.0的核心变化&#xff0c;并通过实战示例展示如何在项目中应用这些新特性。 核心变化概览 Java版…

C# sqlsugar 主子表 联合显示 LeftJoin

在C#中使用SqlSugar ORM进行Left Join操作是一种常见需求&#xff0c;尤其是在处理复杂数据库查询时。SqlSugar是一个轻量级、高性能的ORM框架&#xff0c;支持多种数据库。下面是如何使用SqlSugar进行Left Join操作的示例。1. 安装SqlSugar首先&#xff0c;确保你的项目中已经…

【ROS1】08-ROS通信机制——服务通信

目录 一、概念 二、何时使用服务 三、话题通信与服务通信的区别 四、案例 4.1 C实现 4.1.1 服务端 4.1.2 客户端 4.1.3 测试执行 4.2 Python实现 4.2.1 服务端 4.2.2 客户端 4.2.3 客户端优化——动态传参 4.2.4 客户端优化——等待服务端启动后再发起请求 一、概…

45.sentinel自定义异常

上文提到Blocked by Sentinel(flow limits) 限流异常,这样返给用户就不太友好,所以需要自定义异常。 默认情况下,发生限流、降级、授权拦截时,都会抛出异常到调用方。如果要自定义异常时的返回结果,需要实现BlockExceptionHandler接口: BlockException有很多子类: pac…

f4硬件配置spi

f4型号是stm32f407zgt6用spi来进行MOSI&#xff0c;主机发送从机接收时钟频率设置为1MHzMOSI为PC3&#xff0c;SCK为PB10&#xff0c;CS设置为output->PB12时钟配置如下&#xff1a;波特率计算公式为&#xff1a;128M/(4*Prescaler) 要让波特率为1M&#xff0c;10…

Redis的持久化-RDB

1.持久化一提到持久化&#xff0c;我们就会第一时间联想到M有SQL的事务&#xff0c;MySQL事务有四个比较核心的特征&#xff1a;原子性&#xff08;把多个操作打包成一个整体&#xff09;&#xff0c;一致性&#xff08;事务执行之前和之后&#xff0c;数据都不能离谱&#xff…

前端内存泄漏

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

部署zabbox企业级分布式监控

目录 一、监控系统的基础认知 2.1 监控的定义与核心价值 2.2 监控的五大类型与五层逻辑架构 &#xff08;1&#xff09;五大监控类型 &#xff08;2&#xff09;五层逻辑架构 2.3 主流开源监控产品对比 二、Zabbix 系统深度解析 3.1 Zabbix 的定位与发展历程 3.2 Zabb…

时空数据可视化新范式:基于Three.js的生产全流程时间轴回溯技术解析

内容摘要在现代工业生产中&#xff0c;如何高效地管理和分析生产全流程数据是一个关键问题。传统的数据可视化方法往往只能展示静态的数据快照&#xff0c;难以捕捉和回溯生产过程中的动态变化。然而&#xff0c;基于 Three.js 的时间轴回溯技术为这一难题提供了一种全新的解决…

宝塔面板Nginx报错: IP+端口可以直接从访问,反向代理之后就504了 Gateway Time-out

原因表示代理服务器在等待上游服务器&#xff08;即后端服务&#xff09;响应时超时 &#xff1a;<html><head><title>504 Gateway Time-out</title> </head><body><center><h1>504 Gateway Time-out</h1></center&g…

【ComfyUI学习笔记01】下载安装 | 运行第一个工作流 | 学习思路

【ComfyUI学习笔记01】下载安装 | 运行第一个工作流 | 学习思路前言下载安装ComfyUI的下载和安装ComfyUI Manager 的下载和安装运行第一个工作流初识节点 (Nodes) 工作流案例1 Image Generation绘制流程图&#xff0c;确定关键节点放置关键节点&#xff0c;确定连接顺序补充中间…

numpy库的基础知识

一.numpy是什么 &#xff1f;Numpy 是 Python 中专门用于高性能数值计算的库&#xff0c;其核心是一个功能强大的 n 维数组对象&#xff08;ndarray&#xff09;&#xff0c;可以用来存储和操作大规模的数字矩阵或张量数据。numpy库的作用&#xff1a;核心功能&#xff1a;实现…

在UniApp中防止页面上下拖动的方法

1、pages.json中在某个页面设置禁用弹性滚动的页面 {"path": "pages/yourPage/yourPage","style": {"app-plus": {"bounce": "none"}} } 2、 pages.json中在所有页面设置禁用弹性滚动的页面 {"globalStyl…

LinkedList的模拟实现(双向链表Java)

一&#xff1a;结构LinkedList的底层是双向链表结构(链表后面介绍)&#xff0c;由于链表没有将元素存储在连续的空间中&#xff0c;元素存储在单独的节点中&#xff0c;然后通过引用将节点连接起来了&#xff0c;因此在在任意位置插入或者删除元素时&#xff0c;不需要搬移元素…

Shopify 知识点

&#x1f4dc; 一、Liquid模板语言&#xff08;核心基础&#xff09;语法结构 • 输出变量&#xff1a;{{ product.title }} 动态显示商品标题。 • 逻辑控制&#xff1a;{% if product.available %}…{% endif %} 条件渲染。 • 循环遍历&#xff1a;{% for item in collectio…