rabbitmq-spring-boot-start配置使用手册

rabbitmq-spring-boot-start配置使用手册

文章目录

  • 1.yaml配置如下
  • 2.引入pom依赖如下
    • 2.1 引入项目resources下libs中的jar包依赖如下
    • 2.2引入maven私服依赖如下
  • 3.启动类配置如下
  • 4.项目中测试发送消息如下
  • 5.项目中消费消息代码示例
  • 6.mq管理后台交换机队列创建及路由绑定关系如下

1.yaml配置如下

   rps中的每一个都可以按照Sping官方的RabbitAutoConfiguration自动装配的RabbitProperties的样式来配置,做到了实现配置多个rabbitMq服务器配置和一个rabbitMq服务器下可以配置多个不同类型的交换机和队列进行绑定,还实现了普通队列发送消息、

    一:延迟插件实现延迟队列

        交换机类型必须CustomExchange

    二:TTL + 死信队列/延迟交换机实现延迟队列

    三: 延迟交换机 + 消息设置setHeader(“x-delay”, xxx)

    以下配置了两个不同的rabbitMq服务器,每一个rabbitMq服务器对应多个队列,还配置了两个相同的rabbitMq服务器,只不过两个相同的rabbitMq服务器有不同的交换机,都是一个rabbitMq服务器可以对应相同的一套配置,代码功能服用性强,也方便快捷

## 配置需要保证唯一不重复(eqps中的每一的index唯一,一般配置成递增的,队列交换机绑定关系的bean注入都是根据rps的List下标+eqps中index下标注入保证了唯一性)
zlf:rabbit:rps:## 如果virtual-host不同,在配置一个即可,addresses不同也是可以在配置,eqps的下标以之对应上即可- rabbitmq:virtual-host: /dyict-uataddresses: 192.168.40.61port: 5672username: "admin"password: "admin"- rabbitmq:virtual-host: /testaddresses: 192.168.40.60port: 5672username: "admin"password: "admin"- rabbitmq:virtual-host: /test2addresses: 192.168.40.60port: 5672username: "admin"password: "admin"eqps:## 下标递增且唯一- index: 0eqs:- function-type: Delaydelay-type: 1exchange-type: customexchange-name: zlf.delay.test1queue-name: delay.test1routing-key: delay.test1.keyexchange-args:x-delayed-type: directqueue-args: {}- function-type: Normaldelay-type: 0exchange-type: directexchange-name: zlf.normal.test1queue-name: normal.test1routing-key: normal.test1.keyexchange-args: {}queue-args: {}- function-type: Delaydelay-type: 2exchange-type: directexchange-name: zlf.delay.test2queue-name: delay.test2## 不用监听正常的队列,直接根据同一个路由键去路由,然后监听死信队列routing-key: zlf.delay-test2-keydlx-exchange-name: zlf.dlx-test1dlx-exchange-type: directdlx-queue-name: dlx-test1dlx-key: zlf.dlx-test1-keyexchange-args: {}queue-args:x-dead-letter-exchange: zlf.dlx-test1x-dead-letter-routing-key: zlf.dlx-test1-key## 单位毫秒 30sx-message-ttl: 30000- function-type: Delaydelay-type: 3exchange-type: directexchange-name: zlf.delay.test3queue-name: delay.test3routing-key: zlf.delay-test3-keyexchange-args: {}queue-args: {}- index: 1eqs:- function-type: Delaydelay-type: 1exchange-type: customexchange-name: zlf.delay.test1queue-name: delay.test1routing-key: delay.test1.keyexchange-args:x-delayed-type: directqueue-args: {}- function-type: Normaldelay-type: 0exchange-type: directexchange-name: zlf.normal.test1queue-name: normal.test1routing-key: normal.test1.keyexchange-args: {}queue-args: {}- function-type: Delaydelay-type: 2exchange-type: directexchange-name: zlf.delay.test2queue-name: delay.test2## 不用监听正常的队列,直接根据同一个路由键去路由,然后监听死信队列routing-key: zlf.delay-test2-keydlx-exchange-name: zlf.dlx-test1dlx-exchange-type: directdlx-queue-name: dlx-test1dlx-key: zlf.dlx-test1-keyexchange-args: {}queue-args:x-dead-letter-exchange: zlf.dlx-test1x-dead-letter-routing-key: zlf.dlx-test1-key## 单位毫秒 30sx-message-ttl: 30000- function-type: Delaydelay-type: 3exchange-type: directexchange-name: zlf.delay.test3queue-name: delay.test3routing-key: zlf.delay-test3-keyexchange-args: {}queue-args: {}- index: 2eqs:- function-type: Delaydelay-type: 1exchange-type: customexchange-name: zlf.delay.test1queue-name: delay.test1routing-key: delay.test1.keyexchange-args:x-delayed-type: directqueue-args: {}- function-type: Normaldelay-type: 0exchange-type: directexchange-name: zlf.normal.test1queue-name: normal.test1routing-key: normal.test1.keyexchange-args: {}queue-args: {}- function-type: Delaydelay-type: 2exchange-type: directexchange-name: zlf.delay.test2queue-name: delay.test2## 不用监听正常的队列,直接根据同一个路由键去路由,然后监听死信队列routing-key: zlf.delay-test2-keydlx-exchange-name: zlf.dlx-test1dlx-exchange-type: directdlx-queue-name: dlx-test1dlx-key: zlf.dlx-test1-keyexchange-args: {}queue-args:x-dead-letter-exchange: zlf.dlx-test1x-dead-letter-routing-key: zlf.dlx-test1-key## 单位毫秒 30sx-message-ttl: 30000- function-type: Delaydelay-type: 3exchange-type: directexchange-name: zlf.delay.test3queue-name: delay.test3routing-key: zlf.delay-test3-keyexchange-args: {}queue-args: {}

2.引入pom依赖如下

2.1 引入项目resources下libs中的jar包依赖如下

    右键点击rabbitmq-spring-boot-start-1.0-SNAPSHOT.jar将该jar包手动导入(add as Library),复制该jar包到resources下libs,若果maven自动导入就不用右键手动导入

<dependency><groupId>org.zlf</groupId><artifactId>rabbitmq-spring-boot-start</artifactId><version>1.0-SNAPSHOT</version><scope>system</scope><systemPath>${pom.basedir}/src/main/resources/libs/rabbitmq-spring-boot-start-1.0-SNAPSHOT.jar</systemPath>
</dependency>

2.2引入maven私服依赖如下

<dependency><groupId>org.zlf</groupId><artifactId>rabbitmq-spring-boot-start</artifactId><version>1.0-SNAPSHOT</version>
</dependency>

3.启动类配置如下

@EnableZlfRabbitMq
@Import(value = {RabbitService.class, ZlfMqSpringUtils.class})
@SpringBootApplication(exclude = {RabbitAutoConfiguration.class})

4.项目中测试发送消息如下

    Controller测试可以根据rps的下标 + eqps的index下标来复制多个Controlle类,只需要调用api设置这两个下标对应解析即可发送

rabbitService.sendMsg6(0, 0, msg);

rabbitService.sendMsg6(1, 0, msg);

rabbitService.sendMsg6(2, 0, msg);

,,,,,,,,,,

上面配置了三个下标组合就有以下几种:

0 0 / 01 /11

1 0 / 11 /12

2 0 / 21 / 22

可以复制Controller1、Controller2、Controller3,,,,,,,调用时候只需要指定下标组合即可发送消息

package xxxx.controller;import com.dy.corporate.member.utils.SpringUtils;
import com.zlf.constants.ZlfMqRegistrarBeanNamePrefix;
import com.zlf.service.RabbitService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
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;@Slf4j
@RestController
@RequestMapping("rabbit")
public class RabbitMqTestController {@Autowiredprivate RabbitService rabbitService;@GetMapping("/sendDelayMsg")public String sendDelayMsg(@RequestParam(value = "msg") String msg) {log.info("sendDelayMsg.msg:{}", msg);RabbitTemplate rabbitTemplate = (RabbitTemplate) SpringUtils.getBean(ZlfMqRegistrarBeanNamePrefix.rabbitTemplatePrefix + 0);rabbitService.sendDelayed(rabbitTemplate, "zlf.delay.test1", "delay.test1.key", msg, 10);return "ok";}@GetMapping("/sendDelayMsg2")public String sendDelayMsg2(@RequestParam(value = "msg") String msg) {log.info("sendDelayMsg2.msg:{}", msg);rabbitService.sendMsg6(0, 0, msg);return "ok";}@GetMapping("/sendNormalMsg")public String sendNormalMsg(@RequestParam(value = "msg") String msg) {log.info("sendNormalMsg.msg:{}", msg);RabbitTemplate rabbitTemplate = (RabbitTemplate) SpringUtils.getBean(ZlfMqRegistrarBeanNamePrefix.rabbitTemplatePrefix + 0);rabbitService.sendMsg(rabbitTemplate, "zlf.delay.test1", "delay.test1.key", msg);return "ok";}@GetMapping("/sendNormalMsg2")public String sendNormalMsg2(@RequestParam(value = "msg") String msg) {log.info("sendNormalMsg2.msg:{}", msg);rabbitService.sendMsg6(0, 1, msg);return "ok";}@GetMapping("/sendDelayDlxMsg")public String sendDelayDlxMsg(@RequestParam(value = "msg") String msg) {log.info("sendDelayDlxMsg.msg:{}", msg);RabbitTemplate rabbitTemplate = (RabbitTemplate) SpringUtils.getBean(ZlfMqRegistrarBeanNamePrefix.rabbitTemplatePrefix + 0);//正常发延迟交换机和延迟队列的路由键rabbitService.sendDelayed(rabbitTemplate, "zlf.delay.test2", "zlf.delay-test2-key", msg, 10);return "ok";}@GetMapping("/sendDelayDlxMsg2")public String sendDelayDlxMsg2(@RequestParam(value = "msg") String msg) {log.info("sendDelayDlxMsg2.msg:{}", msg);//正常发延迟交换机和延迟队列的路由键rabbitService.sendDelayed6(0, 2, msg,10);return "ok";}@GetMapping("/sendDelayMsg3")public String sendDelayMsg3(@RequestParam(value = "msg") String msg) {log.info("sendDelayMsg3.msg:{}", msg);rabbitService.sendDelayed6(0, 3, msg, 10);return "ok";}}

项目utils下放入SpringUtils类:

package xxx.utils;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;/*** @author zlf* @description spring上下文工具类* @date 2024/03/11**/
@Component
public class SpringUtils implements ApplicationContextAware {private static final Logger logger = LoggerFactory.getLogger(SpringUtils.class);private static ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {logger.info("应用程序上下文 : [{}]", "开始初始化");SpringUtils.applicationContext = applicationContext;logger.info("应用程序上下文 : [{}]", "初始化完成");}/*** 获取applicationContext*发给* @return*/public static ApplicationContext getApplicationContext() {return applicationContext;}/*** 通过name获取 Bean.** @param name* @return*/public static Object getBean(String name) {return getApplicationContext().getBean(name);}/*** 通过class获取Bean.** @param clazz* @param <T>* @return*/public static <T> T getBean(Class<T> clazz) {return getApplicationContext().getBean(clazz);}/*** 通过name,以及Clazz返回指定的Bean** @param name* @param clazz* @param <T>* @return*/public static <T> T getBean(String name, Class<T> clazz) {return getApplicationContext().getBean(name, clazz);}}

以上测试用例MqConsumer都是可以正常消费到对应队列中的消息的

5.项目中消费消息代码示例

    消费者中只需要指定对应的消费监听工厂即可,监听工厂配置如下:

ZlfMqRegistrarBeanNamePrefix.simpleRabbitListenerContainerFactory + rps的下标

可以复制多个MqConsumer1,MqConsumer2,,,,,,,,,

    然后指定对应的监听工厂配置下标即可,经过测试上面三个配置发送4中发送消息,监听消费都是正常的

package xxx.listener;import com.rabbitmq.client.Channel;
import com.zlf.constants.ZlfMqRegistrarBeanNamePrefix;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;import java.io.IOException;/*** 手动ack业务demo* long deliveryTag = message.getMessageProperties().getDeliveryTag();* try {* int a = 1/0;* User user = JSONObject.parseObject(userStr,User.class);* log.info(user.toString());* //手动ack  第二个参数为false是表示仅仅确认当前消息 true表示确认之前所有的消息* channel.basicAck(deliveryTag,false);* } catch (Exception e) {* //手动nack 告诉rabbitmq该消息消费失败  第三个参数:如果被拒绝的消息应该被重新请求,而不是被丢弃或变成死信,则为true* try {* channel.basicNack(deliveryTag,false,false);* } catch (IOException ex) {* throw new RuntimeException("消息处理失败");* }* }* //channel.basicNack(); 不ack* //channel.basicReject(); 拒绝*/
@Slf4j
@Component
public class MqConsumer {/*** 延迟插件实现延迟队列监听队列消息** @param message* @param channel* @throws IOException*/@RabbitHandler@RabbitListener(queues = "delay.test1", containerFactory = ZlfMqRegistrarBeanNamePrefix.simpleRabbitListenerContainerFactory + 0)public void mqConsumer1(Message message, Channel channel) throws IOException {String msg = new String(message.getBody(), "UTF-8");try {log.info("mqConsumer1=====>msg:{}", msg);} catch (Exception e) {log.error("mqConsumer1消费异常:{}", e.getMessage());} finally {channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);}//channel.basicNack(); 不ack//channel.basicReject(); 拒绝}/*** 普通队列监听队列消息** @param message* @param channel* @throws IOException*/@RabbitHandler@RabbitListener(queues = "normal.test1", containerFactory = ZlfMqRegistrarBeanNamePrefix.simpleRabbitListenerContainerFactory + 0)public void mqConsumer2(Message message, Channel channel) throws IOException {String msg = new String(message.getBody(), "UTF-8");try {log.info("mqConsumer2=====>msg:{}", msg);} catch (Exception e) {log.error("mqConsumer2消费异常:{}", e.getMessage());} finally {channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);}}/*** TTL + 死信队列实现延迟队列监听延迟队列消息(此处省略)* 绑定的那个延迟队列,消息如果正常消费,则不会将消息投递到死信队列上,* 只有消息变成死信才会被投递到死信队列上*//*** TTL + 死信队列实现延迟队列监听死信队列消息* 成为死信的条件* * 1.队列消息长度到达限制。* * 2.消费者拒接消费消息,basicNack/basicReject,并且不把消息重新放入原目标队列,requeue=false。* * 3.原队列存在消息过期设置,消息到达超时时间未被消费。** @param message* @param channel* @throws IOException*/@RabbitHandler@RabbitListener(//监听连接工程指定containerFactory = ZlfMqRegistrarBeanNamePrefix.simpleRabbitListenerContainerFactory + 0,bindings = @QueueBinding(//延迟交换机exchange = @Exchange(value = "zlf.delay.test2",//持久化参数设置durable = "true",//交换机类型指定type = ExchangeTypes.DIRECT),//延迟交换机路由延迟队列的keykey = "zlf.delay-test2-key",//死信队列value = @Queue(value = "dlx-test1",//持久化参数设置durable = "true"//, //autoDelete = "false",)//ignoreDeclarationExceptions = "true")//,//concurrency = "1", // 指定监听该队列的消费者个数//ackMode = "MANUAL"// 手动ack)public void mqConsumer4(Message message, Channel channel) throws IOException {String msg = new String(message.getBody(), "UTF-8");try {log.info("mqConsumer4=====>msg:{}", msg);} catch (Exception e) {log.error("mqConsumer4:{}", e.getMessage());} finally {channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);}}/*** 延迟交换机 + 消息设置setHeader("x-delay", xxx)** @param message* @param channel* @throws IOException*/@RabbitHandler@RabbitListener(queues = "delay.test3", containerFactory = ZlfMqRegistrarBeanNamePrefix.simpleRabbitListenerContainerFactory + 0)public void mqConsumer5(Message message, Channel channel) throws IOException {String msg = new String(message.getBody(), "UTF-8");try {log.info("mqConsumer5=====>msg:{}", msg);} catch (Exception e) {log.error("mqConsumer5消费异常:{}", e.getMessage());} finally {channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);}//channel.basicNack(); 不ack//channel.basicReject(); 拒绝}}

6.mq管理后台交换机队列创建及路由绑定关系如下

    以下交换机和队列定义的时候都是持久化的,上面三个配置示都在rabbitMq的管理后台生成了相同的队列、交换机和绑定关系(唯一不一样的是错误对了是根据rps的List的下标来的,保证唯一),以下截图只展示一个即rps[0]的交换机、队列和绑定关系的创建,其它两个都是一样的(唯一不同就是错误队列交换机是后缀角标是递增的)。

zlf.delay.test1交换机(延迟插件)

img

zlf.delay.test1交换和delay.test1队列的绑定关系:

img

zlf.normal.test1交换机(普通交换机)

img

zlf.normal.test1交换机和normal.test1的绑定关系:

img

zlf.delay.test2交换机:(ttl + 死信队列)

img

zlf.delay.test2交换机和delay.test2绑定关系:

img

zlf.dlx-test1交换机:(死信交换机)

img

zlf.dlx-test1死信交换机和dlx-test1绑定关系:

img

zlf.delay.test3交换机:

img

zlf.delay.test3交换机delay.test3的绑定关系:

img

error交换机

error.direct + 一个下标,类型、路由键是固定

img

error.direct + 一个下标 和 error.queue+ 一个下标 的绑定关系:

img

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

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

相关文章

信息检索(十三):On Complementarity Objectives for Hybrid Retrieval

On Complementarity Objectives for Hybrid Retrieval 摘要1. 引言2. 相关工作2.1 稀疏和密集检索2.2 互补性 3. 提出方法3.1 Ratio of Complementarity (RoC)3.2 词汇表示&#xff08;S&#xff09;3.3 语义表示&#xff08;D&#xff09;3.4 互补目标 4. 实验4.1 实验设置4.2…

关系数据库:关系数据结构基础与概念解析

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

Nginx学习与使用

Nginx 什么是NginxNginx命令Nginx 配置文件文件组成全局块&#xff1a;配置服务器整体运行的配置指令Events块&#xff1a;影响Nginx服务器与用户的网络连接Http块Http全局块Server块全局Server快Location块 配置实例Nginx配置实例——反向代理 什么是Nginx Nginx命令 1.使用…

湖北省地质灾害分布数据 崩塌滑坡泥石流空间分布地质灾害详查等数据集

地质灾害是指在自然或者人为因素的作用下形成的&#xff0c;对人类生命财产造成的损失、对环境造成破坏的地质作用或地质现象。地质灾害在时间和空间上的分布变化规律&#xff0c;既受制于自然环境&#xff0c;又与人类活动有关&#xff0c;往往是人类与自然界相互作用的结果。…

数据资产管理解决方案:构建高效、安全的数据生态体系

在数字化时代&#xff0c;数据已成为企业最重要的资产之一。然而&#xff0c;如何有效管理和利用这些数据资产&#xff0c;却是许多企业面临的难题。本文将详细介绍数据资产管理解决方案&#xff0c;帮助企业构建高效、安全的数据生态体系。 一、引言 在信息化浪潮的推动下&a…

Geostationary IR Channel Brightness Temperature - GridSat B1 -- shell下载

进入网页 https://www.ncei.noaa.gov/products/gridded-geostationary-brightness-temperature 然后进入数据目录&#xff0c;通过https的方式进行下载&#xff1a; 点击后进入如下界面&#xff1a; 点击任意年份进行下载 这里以2004年为例&#xff0c;如下所示&#xff1…

Go语言中的锁与管道的运用

目录 1.前言 2.锁解决方案 3.管道解决方案 4.总结 1.前言 在写H5小游戏的时候&#xff0c;由于需要对多个WebSocket连接进行增、删、查的管理和对已经建立连接的WebSocket通过服务端进行游戏数据交换的需求。于是定义了一个全局的map集合进行连接的管理&#xff0c;让所有…

力扣每日一道系列 --- LeetCode 160. 相交链表

&#x1f4f7; 江池俊&#xff1a; 个人主页 &#x1f525;个人专栏&#xff1a; ✅数据结构探索 ✅LeetCode每日一道 &#x1f305; 有航道的人&#xff0c;再渺小也不会迷途。 LeetCode 160. 相交链表 思路&#xff1a; 首先计算两个链表的长度&#xff0c;然后判断两个链…

华为组网:核心交换机旁挂防火墙,基于ACL重定向配置实验

如图所示&#xff0c;由于业务需要&#xff0c;用户有访问Internet的需求。 用户通过接入层交换机SwitchB和核心层交换机SwitchA以及接入网关Router与Internet进行通信。为了保证数据和网络的安全性&#xff0c;用户希望保证Internet到服务器全部流量的安全性&#xff0c;配置重…

海外社交营销为什么用云手机?不用普通手机?

海外社交营销作为企业拓展海外市场的重要手段&#xff0c;正日益受到企业的青睐。云手机以其成本效益和全球性特征&#xff0c;成为海外社交营销领域的得力助手。那么&#xff0c;究竟是什么特性使得越来越多的企业选择利用云手机进行海外社交营销呢&#xff1f;下文将对此进行…

ARM 寄存器学习:(一)arm多种模式下得寄存器

一.ARM7种状态以及每种状态的寄存器&#xff1a; ARM 处理器共有 7 种不同的处理器模式&#xff0c;在每一种处理器模式中可见的寄存器包括 15 个通用寄存器( R0~R14)、一个或两个(User和Sys不是异常模式&#xff0c;没有spsr寄存器)状态寄存器&#xff08;cpsr和spsr&…

es 集群安全认证

参考文档&#xff1a;Configure security for the Elastic Stack | Elasticsearch Guide [7.17] | Elastic ES敏感信息泄露的原因 Elasticsearch在默认安装后&#xff0c;不提供任何形式的安全防护不合理的配置导致公网可以访问ES集群。比如在elasticsearch.yml文件中,server…

面试算法-51-翻转二叉树

题目 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1] 解 class Solution {public TreeNode invertTree(TreeNode root) {dfs(root);re…

PTA一笔画

作者 张志梅 单位 青岛大学 小丁最近迷恋上一个游戏&#xff0c;传说中的“一笔画”游戏。 那么什么是一笔画&#xff1f;如下图&#xff0c;顾名思义就是一笔可以完成的图。一笔画最基本的要求是在画图的过程中&#xff0c;笔不能离开纸&#xff0c;且笔所画过的线不能重复…

使用Java JDBC连接数据库

在Java应用程序中&#xff0c;与数据库交互是一个常见的任务。Java数据库连接&#xff08;JDBC&#xff09;是一种用于在Java应用程序和数据库之间建立连接并执行SQL查询的标准API。通过JDBC&#xff0c;您可以轻松地执行各种数据库操作&#xff0c;如插入、更新、删除和查询数…

【计算机考研】408全年复习保姆级规划+资料

基础阶段 408一共只分为选择题和大题&#xff0c;选择题80分&#xff0c;大题70分。 基础阶段应该要形成相对完整的知识体系&#xff0c;基础知识大概都需要有印象。 在基础阶段&#xff0c;建议不做大题&#xff0c;把课后选择题都好好的做一遍 第一遍的正确率无需过于关注…

【技术类-05】python实现docx段落文字加粗(Win32)

背景需求&#xff1a; 【技术类-04】python实现docx表格文字和段落文字的“手动换行符&#xff08;软回车&#xff09;”变成“段落标记&#xff08;硬回车&#xff09;”-CSDN博客文章浏览阅读1k次&#xff0c;点赞10次&#xff0c;收藏10次。【技术类-04】python实现docx表格…

three.js 鼠标左右拖动改变玩家视角

这里主要用到了 一个方法 obj.getWorldDirection(); obj.getWorldDirection()表示的获取obj对象自身z轴正方向在世界坐标空间中的方向。 按下 W键前进运动&#xff1b; <template><div><el-container><el-main><div class"box-card-left…

相机与相机模型(针孔/鱼眼/全景相机)

0. 摘要 本文旨在较为直观地介绍相机成像背后的数学模型&#xff0c;主要的章节组织如下&#xff1a; 第1章用最简单的针孔投影模型为例讲解一个三维点是如何映射到图像中的一个像素 第2章介绍除了针孔投影模型外其他一些经典投影模型&#xff0c;旨在让读者建立不同投影模型…

前端 - 基础 表单标签 -- 表单元素( input - type属性) 文本框和密码框

表单元素 &#xff1a; 在表单域中可以定义各种表单元素&#xff0c;这些表单元素就是允许用户在表单中输入或选择 的内容控件。 表单元素的外观也各不一样&#xff0c;有小圆圈&#xff0c;有正方形&#xff0c;也有方框&#xff0c;乱七八糟的&#xff0c;各种各样&#xf…