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

SpringBoot 项目中使用 spring-boot-starter-amqp 依赖实现 RabbitMQ

文章目录

    • 前言
    • 1、application.yml
    • 2、RabbitMqConfig
    • 3、MqMessage
    • 4、MqMessageItem
    • 5、DirectMode
    • 6、StateConsumer:消费者
    • 7、InfoConsumer:消费者

前言

本文是工作之余的随手记,记录在工作期间使用 RabbitMQ 的笔记。

1、application.yml

  • 使用 use 属性,方便随时打开和关闭使用 MQ ,并且可以做到细化控制。
spring:rabbitmq:use: truehost: 10.100.10.100port: 5672username: wenpassword: 123456exchangeSubPush: 'exWen'queueSubPush: 'ha.queue.SubPush'routeSubPush: '1000'exchangeState: sync.ex.StatequeueState: ha.q.ServerqueueStateSync: ha.q.StateServerrouteState: stateexchangeOnlineMonitor: 'sync.ex.State'routeOnlineMonitor: 'state'queueOnlineMonitor: 'ha.q.Online'
  • pom.xml 文件中使用的是 SpringBoot 项目,使用 spring-boot-starter-amqp 依赖。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.wen</groupId><artifactId>springboot-mybatis</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><parent><artifactId>spring-boot-starter-parent</artifactId><groupId>org.springframework.boot</groupId><version>2.5.3</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.18</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.83</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.1</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.18</version></dependency></dependencies>
</project>

2、RabbitMqConfig

  • 配置类,将可配置的参数使用 @Value 做好配置,与 application.yml 相互对应。
package com.wen.mq;import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;@Slf4j
@Configuration
@Data
public class RabbitMqConfig {@Value("${spring.rabbitmq.use:true}")private boolean use;@Value("${spring.rabbitmq.host}")private String host;@Value("${spring.rabbitmq.port}")private int port;@Value("${spring.rabbitmq.username}")private String username;@Value("${spring.rabbitmq.password}")private String password;@Value("${spring.rabbitmq.virtual-host:}")private String virtualHost;@Value("${spring.rabbitmq.exchangeState}")private String exchangeState;@Value("${spring.rabbitmq.queueState}")private String queueState;@Value("${spring.rabbitmq.routeState}")private String routeState;@Value(("${spring.rabbitmq.queueStateSync}"))private String queueStateSync;@Value("${spring.rabbitmq.exchangeOnlineInfo}")private String exchangeOnlineInfo;@Value("${spring.rabbitmq.routeOnlineInfo}")private String routeOnlineInfo;@Value("${spring.rabbitmq.queueOnlineInfo}")private String queueOnlineInfo;@PostConstructprivate void init() {}
}

3、MqMessage

  • MQ 消息实体类
package com.wen.mq;import lombok.Data;@Data
public class MqMessage<T> {private String msgType;private String msgOrigin;private long time;private T data;}

4、MqMessageItem

  • MQ 消息实体类
package com.wen.mq;import lombok.Data;@Data
public class MqMessageItem {private long userId;private String userName;private int userAge;private String userSex;private String userPhone;private String op;}

5、DirectMode

  • 配置中心:使用 SimpleMessageListenerContainer 进行配置。
  • 新加一个消费者队列就要在这里进行配置。
package com.wen.mq;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Slf4j
@Configuration
public class DirectMode {@AutowiredRabbitMqConfig rabbitMqConfig;@Autowiredprivate CachingConnectionFactory connectionFactory;@Autowiredprivate StateConsumer stateConsumer;@Autowiredprivate InfoConsumer infoConsumer;@Beanpublic SimpleMessageListenerContainer initMQ() {if (!rabbitMqConfig.isUse()) {return null;}log.info("begin!");SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);container.setConcurrentConsumers(1);container.setMaxConcurrentConsumers(1);container.setAcknowledgeMode(AcknowledgeMode.MANUAL); // RabbitMQ默认是自动确认,这里改为手动确认// 设置一个队列container.setQueueNames(rabbitMqConfig.getQueueStateSync());//如果同时设置多个队列如下: 前提是队列都是必须已经创建存在的//container.setQueueNames("TestDirectQueue","TestDirectQueue2","TestDirectQueue3”);//另一种设置队列的方法,如果使用这种情况,那么要设置多个,就使用addQueues//container.setQueues(new Queue("TestDirectQueue",true));//container.addQueues(new Queue("TestDirectQueue2",true));//container.addQueues(new Queue("TestDirectQueue3",true));container.setMessageListener(stateConsumer);log.info("end");return container;}@Beanpublic SimpleMessageListenerContainer contactSyncContainer() {if (!rabbitMqConfig.isUse()) {return null;}log.info("contact begin");SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);container.setConcurrentConsumers(1);container.setMaxConcurrentConsumers(1);container.setAcknowledgeMode(AcknowledgeMode.MANUAL); // RabbitMQ默认是自动确认,这里改为手动确认消息//设置一个队列container.setQueueNames(rabbitMqConfig.getQueueOnlineInfo());container.setMessageListener(infoConsumer);log.info("contact end");return container;}@Beanpublic Queue queueState() {if (!rabbitMqConfig.isUse()) {return null;}return new Queue(rabbitMqConfig.getQueueState());}@Beanpublic Queue queueStateSync() {if (!rabbitMqConfig.isUse()) {return null;}return new Queue(rabbitMqConfig.getQueueStateSync());}@BeanDirectExchange exchangeState() {if (!rabbitMqConfig.isUse()) {return null;}return new DirectExchange(rabbitMqConfig.getExchangeState());}@BeanBinding bindingState() {if (!rabbitMqConfig.isUse()) {return null;}return BindingBuilder.bind(queueState()).to(exchangeState()).with(rabbitMqConfig.getRouteState());}@BeanBinding bindingStateSync() {if (!rabbitMqConfig.isUse()) {return null;}return BindingBuilder.bind(queueStateSync()).to(exchangeState()).with(rabbitMqConfig.getRouteState());}// 新加一个消费者@Beanpublic Queue queueOnlineMonitor() {if (!rabbitMqConfig.isUse()) {return null;}return new Queue(rabbitMqConfig.getQueueOnlineInfo());}@BeanDirectExchange exchangeOnlineMonitor() {if (!rabbitMqConfig.isUse()) {return null;}return new DirectExchange(rabbitMqConfig.getExchangeOnlineInfo());}@BeanBinding bindingExchangeOnlineMonitor() {if (!rabbitMqConfig.isUse()) {return null;}return BindingBuilder.bind(queueOnlineMonitor()).to(exchangeOnlineMonitor()).with(rabbitMqConfig.getRouteOnlineInfo());}
}

6、StateConsumer:消费者

  • 实现 ChannelAwareMessageListener 接口,可以在这里面做相应的操作,例如存缓存,存库等。
package com.wen.mq;import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;@Slf4j
@Component
public class StateConsumer implements ChannelAwareMessageListener {@AutowiredRabbitMqConfig rabbitMqConfig;@Overridepublic void onMessage(Message message, Channel channel) throws Exception {String queueName = message.getMessageProperties().getConsumerQueue();long deliveryTag = message.getMessageProperties().getDeliveryTag();if (!rabbitMqConfig.getQueueStateSync().equals(queueName)) {String bodyStr = new String(message.getBody(), StandardCharsets.UTF_8);try {MqMessage<List<MqMessageItem>> mqMessage = JSON.parseObject(bodyStr, new TypeReference<MqMessage<List<MqMessageItem>>>() {});// 这里可以对消息做其他处理,例如存储到缓存中List<MqMessageItem> items = mqMessage.getData();if (CollectionUtil.isNotEmpty(items)) {applyToRedis(mqMessage);}log.info("consume mq msg ok, queue:{}, deliveryTag:{}, msg:{}", queueName, deliveryTag, mqMessage);channel.basicAck(deliveryTag, false);} catch (JSONException e) {log.error("parse mq msg exception, queue:{}, deliveryTag:{}", queueName, deliveryTag, e);channel.basicReject(deliveryTag, false);} catch (Exception e) {log.error("consume mq msg exception, queue:{}, deliveryTag:{}", queueName, deliveryTag, e);channel.basicReject(deliveryTag, true); //为true会重新放回队列}}}public static final String MQ_STATE_OP_REMOVE_STATE = "REMOVE_STATE";public static final String MQ_STATE_OP_CHANGE_STATE = "CHANGE_STATE";private void applyToRedis(MqMessage<List<MqMessageItem>> mqMessage) {List<MqMessageItem> data = mqMessage.getData();Map<String, List<MqMessageItem>> itemGroupByOp = data.stream().collect(Collectors.groupingBy(item -> item.getOp()));List<MqMessageItem> stateToRemove = itemGroupByOp.get(MQ_STATE_OP_REMOVE_STATE);List<MqMessageItem> stateToChange = itemGroupByOp.get(MQ_STATE_OP_CHANGE_STATE);if (CollectionUtil.isNotEmpty(stateToRemove)) {Map<Long, Set<String>> map = new HashMap<>();for (MqMessageItem item : stateToRemove) {map.computeIfAbsent(item.getUserId(), u -> new HashSet<>()).add(String.valueOf(item.getUserAge()));}// cacheService.removeUserState(map);}if (CollectionUtil.isNotEmpty(stateToChange)) {List<MqMessageItem> list = stateToChange.stream().map(u -> {MqMessageItem dto = new MqMessageItem();dto.setUserId(u.getUserId());dto.setUserAge(u.getUserAge());dto.setUserName(u.getUserName());dto.setUserSex(u.getUserSex());dto.setUserPhone(u.getUserPhone());return dto;}).collect(Collectors.toList());// cacheService.saveUserState(list);}}
}

7、InfoConsumer:消费者

  • 实现 ChannelAwareMessageListener 接口,可以在这里面做相应的操作,例如存缓存,存库等。
package com.wen.mq;import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Slf4j
@Component
public class InfoConsumer implements ChannelAwareMessageListener {@AutowiredRabbitMqConfig rabbitMqConfig;@Overridepublic void onMessage(Message message, Channel channel) throws Exception {String queueName = message.getMessageProperties().getConsumerQueue();log.info("queueName: {}", queueName);long deliveryTag = message.getMessageProperties().getDeliveryTag();try {byte[] body = message.getBody();String content = new String(body);MqMessage msg = JSONObject.parseObject(content, MqMessage.class);if (rabbitMqConfig.getQueueOnlineInfo().equals(queueName)) {// 订阅到的消息就是变更的消息// 这里可使用service对消息进行消费,返回一个booleanlog.info("用户监控数据写入失败!数据:{}", msg);}log.info("consume mq msg ok, queue:{}, deliveryTag:{}, msg:{}", queueName, deliveryTag, msg);channel.basicAck(deliveryTag, false);} catch (JSONException e) {log.error("parse mq msg exception, queue:{}, deliveryTag:{}", queueName, deliveryTag, e);channel.basicReject(deliveryTag, false); //为true会重新放回队列} catch (Exception e) {log.error("consume mq msg exception, queue:{}, deliveryTag:{}", queueName, deliveryTag, e);channel.basicReject(deliveryTag, true); //为true会重新放回队列}}
}

相关文章:

SpringBoot 项目中使用 spring-boot-starter-amqp 依赖实现 RabbitMQ

文章目录 前言1、application.yml2、RabbitMqConfig3、MqMessage4、MqMessageItem5、DirectMode6、StateConsumer&#xff1a;消费者7、InfoConsumer&#xff1a;消费者 前言 本文是工作之余的随手记&#xff0c;记录在工作期间使用 RabbitMQ 的笔记。 1、application.yml 使…...

Uniapp 安装安卓、IOS模拟器并调试

一、安装Android模拟器并调试 1. 下载并安装 Android Studio 首先下载 Mac 环境下的 Android Studio 的安装包&#xff0c;为dmg 格式。 下载完将Android Studio 向右拖拽到Applications中&#xff0c;接下来等待安装完成就OK啦&#xff01; 打开过程界面如下图所示&#xf…...

JavaScript 中的原型和原型链

JavaScript 中的原型和原型链也是一个相对较难理解透彻的知识点&#xff0c;下面结合详细例子来进行说明&#xff1a; 一、原型的概念 在 JavaScript 中&#xff0c;每个函数都有一个 prototype 属性&#xff0c;这个属性指向一个对象&#xff0c;这个对象就是所谓的 “原型对…...

数组变换(两倍)

数组变换 以最大元素为基准元素&#xff0c;判读其他元素能否通过 x 2 成为最大值&#xff01; 那么怎么判断呢&#xff1a; max % arr[i] 0arr[i] * 2 ^n max int x 2 ^ n max / arr[i] 3.只需判断 这个 x 是不是 2 的 n 次放就可以了&#xff01; 判断 是否为 2 的 n 次 …...

GBN协议、SR协议

1、回退N步&#xff08;Go-Back-N,GBN&#xff09;协议&#xff1a; 总结&#xff1a; GBN协议的特点&#xff1a; &#xff08;1&#xff09;累计确认机制&#xff1a;当发送方收到ACKn时&#xff0c;表明接收方已正确接收序号为n以及序号小于n的所有分组&#xff0c;发送窗…...

三维扫描检测仪3d扫描测量尺寸-自动蓝光测量

在现代工业及生产过程中&#xff0c;精确、高效的尺寸检测是保证产品质量、提升生产效率的关键因素。 红、蓝光测量&#xff0c;以其高精度、高效率和非接触式的特点&#xff0c;在工业及生产中发挥着越来越重要的作用。蓝光测量技术利用蓝色激光光源&#xff0c;通过扫描被测…...

大模型翻译能力评测

1. 背景介绍 随着自然语言处理技术的飞速发展&#xff0c;机器翻译已经成为一个重要的研究领域。近年来&#xff0c;基于大模型的语言模型在机器翻译任务上取得了显著的进展。这些大模型通常具有数亿甚至数千亿的参数&#xff0c;能够更好地理解和生成自然语言。 但是&#xf…...

MySQL隐式转换造成索引失效

一、什么是 MySQL 的隐式转换&#xff1f; MySQL 在执行查询语句时&#xff0c;有时候会自动帮我们进行数据类型的转换&#xff0c;这个过程就是隐式转换。比如说&#xff0c;我们在一个 INT 类型的字段上进行查询&#xff0c;但是传入的查询条件却是字符串类型的值&#xff0c…...

SuperMap Objects组件式GIS开发技术浅析

引言 随着GIS应用领域的扩展&#xff0c;GIS开发工作日显重要。一般地&#xff0c;从平台和模式上划分&#xff0c;GIS二次开发主要有三种实现方式&#xff1a;独立开发、单纯二次开发和集成二次开发。上述的GIS应用开发方式各有利弊&#xff0c;其中集成二次开发既可以充分利…...

多组数输入a+b:JAVA

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 输入描述: 输入包含多组数据&#xff0c;每组数据输入一行&#xff0c;包含两个整数 输出描述: 对于每组数据输出一行包含一个整数表示两个整数的和 代码: import java.util.Scanner; pu…...

R语言结构方程模型(SEM)在生态学领域中的应用

目录 专题一、R/Rstudio简介及入门 专题二、结构方程模型&#xff08;SEM&#xff09;介绍 专题三&#xff1a;R语言SEM分析入门&#xff1a;lavaan VS piecewiseSEM 专题四&#xff1a;SEM全局估计&#xff08;lavaan&#xff09;在生态学领域高阶应用 专题五&#xff1…...

架构-微服务-服务调用Dubbo

文章目录 前言一、Dubbo介绍1. 什么是Dubbo 二、实现1. 提供统一业务api2. 提供服务提供者3. 提供服务消费者 前言 服务调用方案--Dubbo‌ 基于 Java 的高性能 RPC分布式服务框架&#xff0c;致力于提供高性能和透明化的 RPC远程服务调用方案&#xff0c;以及SOA服务治理方案。…...

【SpringBoot问题】IDEA中用Service窗口展示所有服务及端口的办法

1、调出Service窗口 打开View→Tool Windows→Service&#xff0c;即可显示。 2、正常情况应该已经出现SpringBoot&#xff0c;如下图请继续第三步 3、配置Service窗口的项目启动类型。微服务一般是Springboot类型。所以这里需要选择一下。 点击最后一个号&#xff0c;点击Ru…...

OpenCV 图像轮廓查找与绘制全攻略:从函数使用到实战应用详解

摘要&#xff1a;本文详细介绍了 OpenCV 中用于查找图像轮廓的 cv2.findContours() 函数以及绘制轮廓的 cv2.drawContours() 函数的使用方法。涵盖 cv2.findContours() 各参数&#xff08;如 mode 不同取值对应不同轮廓检索模式&#xff09;及返回值的详细解析&#xff0c;搭配…...

电机驱动MCU介绍

电机驱动MCU是一种专为电机控制设计的微控制器单元&#xff0c;它集成了先进的控制算法和高性能的功率输出能力。 电机驱动MCU采用高性能的处理器核心&#xff0c;具有快速的运算速度和丰富的外设接口。它内置了专业的电机控制算法&#xff0c;包括PID控制、FOC&#xff08;Fi…...

人工智能学习框架详解及代码使用案例

人工智能学习框架详解及代码使用案例 人工智能(AI)学习框架是构建和训练AI模型的基础工具,它们提供了一组预定义的算法、函数和工具,使得开发者能够更快速、更高效地构建AI应用。本文将深入探讨人工智能学习框架的基本概念、分类、优缺点、选择要素以及实际应用,并通过代…...

修改Textview中第一个字的字体,避免某些机型人民币¥不显示

在 Android 中&#xff0c;系统提供了三种常用的字体类型&#xff0c;分别是&#xff1a; Serif&#xff08;衬线字体&#xff09;: 这种字体有明显的衬线或笔画末端装饰&#xff0c;通常用于印刷品和书籍&#xff0c;给人一种正式和优雅的感觉。示例&#xff1a;Typeface.SERI…...

彻底理解quadtree四叉树、Octree八叉树 —— 点云的空间划分的标准做法

1.参考文章&#xff1a; &#xff08;1&#xff09;https://www.zhihu.com/question/25111128 这里面的第一个回答&#xff0c;有一幅图&#xff1a; 只要理解的四叉树的构建&#xff0c;对于八叉树的构建原理类比方法完全一样&#xff1a;对于二维平面内的随机分布的这些点&…...

Python时间序列优化之道滑动与累积窗口的应用技巧

大家好&#xff0c;在时间序列数据处理中&#xff0c;通常会进行滑动窗口计算(rolling)和累积窗口计算(expanding)等操作&#xff0c;以便分析时间序列的变化趋势或累积特征。Pandas提供的rolling和expanding函数提供了简单、高效的实现方式&#xff0c;特别适用于金融、气象、…...

Buffered 和 BuffWrite

Buffered和BuffWrite是Java IO包中的两个类&#xff0c;用于提高IO操作的效率。 Buffered是一个缓冲区类&#xff0c;可以将一个InputStream或者一个Reader包装起来&#xff0c;提供了一定的缓冲区大小&#xff0c;可以一次读取多个字节或字符&#xff0c;减少了读取的次数&am…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

Linux nano命令的基本使用

参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时&#xff0c;显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

django blank 与 null的区别

1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是&#xff0c;要注意以下几点&#xff1a; Django的表单验证与null无关&#xff1a;null参数控制的是数据库层面字段是否可以为NULL&#xff0c;而blank参数控制的是Django表单验证时字…...

抽象类和接口(全)

一、抽象类 1.概念&#xff1a;如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象&#xff0c;这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法&#xff0c;包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中&#xff0c;⼀个类如果被 abs…...

ui框架-文件列表展示

ui框架-文件列表展示 介绍 UI框架的文件列表展示组件&#xff0c;可以展示文件夹&#xff0c;支持列表展示和图标展示模式。组件提供了丰富的功能和可配置选项&#xff0c;适用于文件管理、文件上传等场景。 功能特性 支持列表模式和网格模式的切换展示支持文件和文件夹的层…...

jdbc查询mysql数据库时,出现id顺序错误的情况

我在repository中的查询语句如下所示&#xff0c;即传入一个List<intager>的数据&#xff0c;返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致&#xff0c;会导致返回的id是从小到大排列的&#xff0c;但我不希望这样。 Query("SELECT NEW com…...