EMQX安装和Java订阅、发布mqtt消息

一、EMQX介绍 EMQX是大规模分布式MQTT消息服务器,可以高效可靠连接海量物联网设备,实时处理分发消息与事件流数据,助力构建关键业务的物联网与云应用。EMQX 作为物联网应用开发和物联网平台搭建必须用到的基础设施软件,主要在边缘和云端实现物联网设备互联与设备上云,提供物联网设备接入、协议处理、消息路由、数据存储、流数据处理等核心能力。 二、EMQX安装 访问官网下载安装包:下载 EMQX 解压zip文件得到软件目录 运行EMQX,打开cmd命令窗口,进入软件bin目录,输入emqx start命令启动软件 登录emqx控制台,访问http://127.0.0.1:18083/,默认用户名、密码是admin、public。 三、Java实现发送和订阅消息 3.1 创建客户端基础代码 引入pom依赖 <dependency> <groupId>org.eclipse.paho</groupId> <artifactId>org.eclipse.paho.client.mqttv3</artifactId> <version>1.2.2</version> </dependency> 订阅和发布消息相关代码 import org.eclipse.paho.client.mqttv3.*; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; public class App { public static void main(String[] args) { String subTopic = "testtopic/#"; String pubTopic = "testtopic/1"; String content = "Hello World"; int qos = 2; String broker = "tcp://127.0.0.1:1883"; String clientId = "emqx_test"; MemoryPersistence persistence = new MemoryPersistence(); try { MqttClient client = new MqttClient(broker, clientId, persistence); // MQTT 连接选项 MqttConnectOptions connOpts = new MqttConnectOptions(); connOpts.

Transformer模型详解

1. 前言 transformer结构是google在2017年的Attention Is All You Need论文中提出,在NLP的多个任务上取得了非常好的效果,可以说目前NLP发展都离不开transformer。最大特点是抛弃了传统的CNN和RNN,整个网络结构完全是由Attention机制组成。 由于其出色性能以及对下游任务的友好性或者说下游任务仅仅微调即可得到不错效果,在计算机视觉领域不断有人尝试将transformer引入,近期也出现了一些效果不错的尝试,典型的如目标检测领域的detr和可变形detr,分类领域的vision transformer等等。 本文从transformer结构出发,结合视觉中的transformer成果(具体是vision transformer和detr)进行分析。 1.1. Transformer 概览 首先,让我们先将 Transformer 模型视为一个黑盒,如下图所示。在机器翻译任务中,将一种语言的一个句子作为输入,然后将其翻译成另一种语言的一个句子作为输出。 Transformer 模型(黑盒模式) Transformer 本质上是一个 Encoder-Decoder 架构。因此中间部分的 Transformer 可以分为两个部分:编码组件和解码组件。如下图所示: Transformer 模型(Encoder-Decoder 架构模式) 其中,编码组件由多层编码器(Encoder)组成(在论文中作者使用了 6 层编码器,在实际使用过程中你可以尝试其他层数)。解码组件也是由相同层数的解码器(Decoder)组成(在论文也使用了 6 层)。如下图所示: 每个编码器由两个子层组成:Self-Attention 层(自注意力层)和 Position-wise Feed Forward Network(前馈网络,缩写为 FFN)如下图所示。每个编码器的结构都是相同的,但是它们使用不同的权重参数。 编码器的输入会先流入 Self-Attention 层。它可以让编码器在对特定词进行编码时使用输入句子中的其他词的信息(可以理解为:当我们翻译一个词时,不仅只关注当前的词,而且还会关注其他词的信息)。后面我们将会详细介绍 Self-Attention 的内部结构。然后,Self-Attention 层的输出会流入前馈网络。 解码器也有编码器中这两层,但是它们之间还有一个注意力层(即 Encoder-Decoder Attention),其用来帮忙解码器关注输入句子的相关部分(类似于 seq2seq 模型中的注意力)。 1.2. 引入张量 现在我们已经了解了模型的主要组成部分,让我们开始研究各种向量/张量,以及他们在这些组成部分之间是如何流动的,从而将输入经过已训练的模型转换为输出。 和通常的 NLP 任务一样,首先,我们使用词嵌入算法(Embedding)将每个词转换为一个词向量。在 Transformer 论文中,词嵌入向量的维度是 512。 每个词被嵌入到大小为 512 的向量中。我们将用这些简单的框代表这些向量。 嵌入仅发生在最底层的编码器中。所有编码器都会接收到一个大小为 512 的向量列表——底部编码器接收的是词嵌入向量,其他编码器接收的是上一个编码器的输出。这个列表大小是我们可以设置的超参数——基本上这个参数就是训练数据集中最长句子的长度。 对输入序列完成嵌入操作后,每个词都会流经编码器的两层。 接下来,我们将换一个更短的句子作为示例,来说明在编码器的每个子层中发生了什么。 上面我们提到,编码器会接收一个向量作为输入。编码器首先将这些向量传递到 Self-Attention 层,然后传递到前馈网络,最后将输出传递到下一个编码器。

stable diffusion使用相关

IP Adapter,我愿称之它为SD垫图 IP Adapter是腾讯lab发布的一个新的Stable Diffusion适配器,它的作用是将你输入的图像作为图像提示词,本质上就像MJ的垫图。 IP Adapter比reference的效果要好,而且会快很多,适配于各种stable diffusion模型,还能和controlnet等一起用。 目前更新了faceID模型,专门用于人脸的 然后支持了stable diffusion xl,但是还没支持turbo模型 作者回复:这正在考虑中,但尚未实施(似乎 SDXL turbo 的训练代码尚未发布) 23.12 模型基础知识 主模型等通常16位就行,不带fp16的代表fp32模型,带来的效果提升不显著却占了很大空间。我们不用下载这些。 Diffusers库学习 来源:https://zhuanlan.zhihu.com/p/672574978 简介: 扩散模型相关的工具包,可以帮助推理,训练等。类似于pytorch开源的TorchVision库,不过这个库开源性,实时性,都更强。 目前很多研究论文都是直接基于Diffusers库开发他们的代码。 特色优点: 开源性强(一个论文都可以把自己模型相关的代码贡献进去)、 实效性强:最新的模型架构很快能得到工具支持,比如新出的xl模型,lcm加速,想用直接掉他的接口就行了,不用自己适配一遍各种配置,自己写个接口,再进行调用 接口简单,非常适合小白入门文生图、图生图等研究,同样也极大地方便了大佬们对代码的迭代优化。 官方介绍: Diffusers 都是一个支持两者的模块化工具箱。我们的库在设计时注重可用性而不是性能,简单而不是容易,可定制性而不是抽象。 网友评价:Diffusers架构比较好,开发体验好,不过支持配置的东西没那么多。 我们直接找到典中典那五行代码 from diffusers import DiffusionPipeline import torch pipeline = DiffusionPipeline.from_pretrained(“runwayml/stable-diffusion-v1-5”, torch_dtype=torch.float16) pipeline.to(“cuda”) pipeline(“An image of a squirrel in Picasso style”).images[0] 运行这段代码它会自动替你下载,模型之又多又大、网速之慢(不fq的话),十分感人。 支持本地路径,可以自己下载保存,把url改成本地路径的url就行了,似乎还要添加 variant='fp16’的参数,不然无法识别fp16的模型。 既然是代码级讲解,我很有必要讲一讲这个DiffusionPipeline。如果你想要全面进入Diffusers的广阔天地,了解Diffusers库的核心Pipeline是一大关键。 Pipeline基本结构 Pipeline是Diffusers库的最大单位,一个pipeline就可以让你在五行之内实现文生图功能。由此可见,一个pipeline模块的代码量是相当庞大的。 事实上,一个pipeline包含了如下四大件(含大模型文件): VAE,图像变到潜空间,或者反之。缩小图像,给Unet生成。或者反之。 UNet,CNN网络,噪声预测的部分 Text-Encoder,用于把tokens编码为一串向量,用来控制扩散模型的生成。他有附属组件 Tokenizer,把输入的文本按照字典编码为tokens Scheduler,采样规划器,控制采样方法,采样过程的。 其它小模块: Safety_checker,NSFW检测器,很多人应该都不想要这个(shide),后面我会讲怎么去掉这一部分 Feature_extractor,也是NSFW检测器的一部分,也可以去掉。 StableDiffusionPipeline的每一个模块都对应一个类,如VAE模块对应的是diffusers库中的AutoencoderKL类,所以说StableDiffusionPipeline类的初始化会同时完成七个子模块对应类的初始化。 Diffusers库中的大多数类我们首先就要看__init__()函数和__call()函数。和torch的model类似的。

java.net.SocketTimeoutException: Read timed out

全套面试题已打包2024最全大厂面试题下载 引言 在进行网络编程时,我们经常会遇到java.net.SocketTimeoutException: Read timed out异常,这个异常通常在网络通信过程中出现,给开发者带来了一定的困惑。本文将深入解析SocketTimeoutException异常的原因,并提供一些避免该异常的策略。 什么是SocketTimeoutException异常? SocketTimeoutException异常是java.net.SocketTimeoutException的一种异常情况。它通常在进行网络通信时出现,当一个读操作在指定的时间内没有完成时,Java网络编程会抛出SocketTimeoutException异常。 以下是一个示例代码,展示了这个异常的触发情况: public void performNetworkOperation() { try { // 创建Socket对象 Socket socket = new Socket("example.com", 80); // 设置读取超时时间 socket.setSoTimeout(5000); // 执行网络操作 // ... } catch (SocketTimeoutException e) { // 处理SocketTimeoutException异常 // ... } catch (IOException e) { // 处理其他IO异常 // ... } } 在上述代码中,我们创建了一个Socket对象,并通过setSoTimeout()方法设置读取超时时间为5秒。如果在5秒内没有完成读取操作,Java网络编程会抛出SocketTimeoutException异常。 异常产生的原因 SocketTimeoutException异常的产生是由于网络通信过程中读取操作未能在指定的超时时间内完成。这可能是因为网络延迟、服务器响应时间过长或者网络连接不稳定等原因。 解析SocketTimeoutException异常 要深入理解SocketTimeoutException异常,我们需要了解其继承关系。SocketTimeoutException是java.io.InterruptedIOException的子类,而java.io.InterruptedIOException又是java.io.IOException的子类。因此,SocketTimeoutException异常是IOException的一种特殊情况。 SocketTimeoutException异常提供了一个重要的方法getTimeout(),该方法返回引发异常的超时时间。通过调用getTimeout()方法,我们可以获取到超时时间,并根据需要进行相应的处理。 以下是一个示例代码,展示了如何使用getTimeout()方法来处理超时时间: public void performNetworkOperation() { try { // 创建Socket对象 Socket socket = new Socket("

Android视频播放之VideoView

1、VideoView类介绍 Android的VideoView组件可以从不同的来源(例如资源文件或内容提供器)读取图像,计算和维护视频的画面尺寸以使其适用于任何布局管理器,并提供一些诸如缩放、着色之类的显示选项,包含在widget下面:android.widget.VideoView。Android中视屏播放框架如下图: 从图中可以看出,VideoView组件进行视频播放的过程可以分为三步: (1)JAVA Framework层,应用程序进来之后到VideoView,再经过Surface; (2)Native Framework层,先到SurfaceFlinger,然后到OverlayHal,同时借助了PVPlayer; (3)Driver层,利用Main framebuffer和Video Plane进行播放; VideoView组件的类继承与接口实现情况为: 继承:public class VideoView extends SurfaceView 接口:implements MediaController.MediaPlayerControl 而从Object开始的继承层次如下: java.lang.Object android.view.View android.view.SurfaceView android.widget.VideoView VideoView类的构造函数有三个: (1)public VideoView(Context context),创建一个默认属性的VideoView实例。参数context为视图运行的应用程序上下文,通过它可以访问当前主题、资源等等。注:以下描述中重复参数的解释就不给出了。 (2)public VideoView(Context context, AttributeSet attrs),创建一个带有attrs属性的VideoView实例。attrs用于视图的 XML 标签属性集合。 (3)public VideoView(Context context, AttributeSet attrs, int defStyle),创建一个带有attrs属性,并且指定其默认样式的VideoView实例。参数defStyle为应用到视图的默认风格,如果为 0 则不应用(包括当前主题中的)风格,该值可以是当前主题中的属性资源,也可以是明确的风格资源ID。 比较常用的共有方法有播放start()、暂停pause()等,具体描述与用法见后面测试部分。 2、视频播放代码 先给出一个简单的测试案例,程序中以File和Uri两种形式来给VideoView组件加载手机SD卡中的视频资源。资源类型为MP4,使用手机自带摄像机录制,完整路径名为“/mnt/sdcard/Pictures/video.mp4”。在代码采用的是读取系统路径的方式:Environment.getExternalStorageDirectory() + "/Pictures/video.mp4"。 另外说明一点,利用Uri对网络资源进行读取的方式和本地资源类似,只是资源名称的形式不同。如: Uri uri = Uri.parse("rtsp://v2.cache2.c.youtube.com/CjgLENy73wIaLwm3JbT_%ED%AF%80%ED%B0%819HqWohMYESARFEIJbXYtZ29vZ2xlSARSB3Jlc3VsdHNg_vSmsbeSyd5JDA==/0/0/0/video.3gp"); 文件格式3gp也是VideoView组件支持格式中的一种。 由于要对手机中的文件进行读取,所以必须在AndroidManifest.xml文件中添加用户权限: 1 <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> 2 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 3 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 程序中用到的String变量封装在了string.xml中: 1 <resources> 2 <string name="

借助gpt生成ppt:文心一言(chatgpt)、chatppt

提供一种简单的基于gpt快速生成ppt的方式。前置条件: 文心一言chatpptwps/office ppt Step1: 下载chatppt插件 https://chat-ppt.com/invitelinke?share_code=38368842&channel=chat-ppt.com 注册地址 下载完成后,安装即可,安装完成后,会看到如下页面(以wps为例): Step2:借助文心一言生成大纲 文心一言地址: https://yiyan.baidu.com/ 如下截图: 一定要注意:这里要规定好格式 请给予你的回答,帮我制作一篇内容为《车辆行驶证数据查询》PPT大纲,要求如下: 第一、一定要使用中文。 第二、页面形式有3种,封面、目录、列表。 第三、目录页要列出内容大纲。 第四、根据内容大纲,生成对应的PPT列表页,每一页PPT列表页使用=====列表=====开头。 第五、封面页格式如下: =====封面===== # 主标题 ## 副标题 演讲人:我的名字 第六、目录页格式如下: =====目录===== # 目录 ## CONTENT 1、内容 2、内容 第七、列表页格式如下: =====列表===== # 页面主标题 1、要点一 要点一的描述内容 2、要点二 要点二的描述内容 2、要点三 要点三的描述内容 第八、每页列表页至少要写3项要点,并且每个要点必须写50字以内的要点描述,并且要点和描述要一一对应。 第九、列表页里的要点描述内容是对要点的详细描述,10个字以上,50个字以内。 最后,一定要使用代码块回复你生成的内容,切记切记。 复制出markdown中有用的信息: 如下: =====封面===== # 车辆行驶证数据查询 ## 为您揭示车辆行驶数据的奥秘 演讲人:XXX =====目录===== # 目录 ## CONTENT 1、引言 2、行驶证数据查询的重要性 3、如何进行行驶证数据查询 4、查询结果的解读与应用 5、案例分享与效果展示 6、总结与展望 =====列表===== # 引言 1、介绍主题:车辆行驶证数据查询 2、简述车辆行驶证数据的含义和价值 3、提出本演示文稿的主要内容与目的 # 行驶证数据查询的重要性 1、了解车辆行驶状况的需求 2、行驶证数据的可靠来源 3、行驶证数据在交通管理中的应用价值 4、行驶证数据在保险和金融行业的应用价值 # 如何进行行驶证数据查询 1、查询方式:线上查询、线下查询 2、查询流程:输入车牌号及车颜色等信息查询,返回车辆驾驶总里程,驾驶总时长,平均驾驶速度等驾驶数据信息。 3、注意事项:确保信息的准确性、合法性及安全性 # 查询结果的解读与应用 1、查询结果的组成与解读 2、如何根据查询结果评估车辆状况和驾驶行为 3、查询结果在交通管理中的应用示例 4、查询结果在保险和金融行业的应用示例 # 案例分享与效果展示 1、案例一:交通管理部门应用案例 2、案例二:保险公司应用案例 3、案例三:个人用户应用案例 4、案例效果总结与展示 # 总结与展望 1、行驶证数据查询的重要性和应用价值总结 2、未来发展与展望:技术进步与行业应用拓展 Step3 生成ppt 在ppt中粘贴回车即可:

Python中的三目运算符详解

在Python中,三目运算符是一种简洁的条件表达式,也称为条件运算符。它允许在一行代码中根据条件的真假来选择不同的值或表达式。本文将详细介绍Python中的三目运算符,包括语法、用法示例和最佳实践。 三目运算符的基本语法 Python的三目运算符的基本语法如下: value_if_true if condition else value_if_false condition:一个条件表达式,如果为True,返回value_if_true;如果为False,返回value_if_false。value_if_true:如果条件为True,返回的值或表达式。value_if_false:如果条件为False,返回的值或表达式。 三目运算符是一种紧凑的方式来表示条件语句,通常用于替代简单的if-else语句。 三目运算符的用法示例 通过一些具体的示例来了解三目运算符的用法。 示例 1:判断数字的奇偶性 以下示例演示如何使用三目运算符来判断一个数字是奇数还是偶数: num = 10 result = "偶数" if num % 2 == 0 else "奇数" print(result) # 输出: "偶数" 在这个示例中,使用三目运算符根据num % 2 == 0的真假来选择返回值,从而判断数字的奇偶性。 示例 2:计算绝对值 以下示例演示如何使用三目运算符来计算一个数的绝对值: num = -5 absolute_value = num if num >= 0 else -num print(absolute_value) # 输出: 5 在这个示例中,使用三目运算符来判断num是否大于等于0,如果是,就返回num本身,否则返回-num。 示例 3:选择最大值 以下示例演示如何使用三目运算符来选择两个数中的最大值: a = 10 b = 15 max_value = a if a > b else b print(max_value) # 输出: 15 在这个示例中,使用三目运算符来比较a和b的大小,然后选择较大的那个值。

解决MapStruct映射处理器报错:java: Internal error in the mapping processor: java.lang.NullPointerException

引言 MapStruct是一个强大的Java映射框架,它能够在编译时生成映射代码,提高了映射的性能。然而,有时候在使用MapStruct时可能会遇到一些问题,其中之一就是java: Internal error in the mapping processor: java.lang.NullPointerException错误。 错误原因 这个错误通常是由于MapStruct在处理映射时出现了空指针异常引起的。可能的原因是: 版本兼容性问题: 使用不兼容的MapStruct版本可能导致内部处理器错误。 <!--MapStruct 依赖--> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>1.3.1.Final</version> </dependency> <!--MapStruct 注解处理器--> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.3.1.Final</version> </dependency> java: Internal error in the mapping processor: java.lang.NullPointerException at org.mapstruct.ap.internal.processor.DefaultVersionInformation.createManifestUrl(DefaultVersionInformation.java:182) at org.mapstruct.ap.internal.processor.DefaultVersionInformation.openManifest(DefaultVersionInformation.java:153) at org.mapstruct.ap.internal.processor.DefaultVersionInformation.getLibraryName(DefaultVersionInformation.java:129) at org.mapstruct.ap.internal.processor.DefaultVersionInformation.getCompiler(DefaultVersionInformation.java:122) at org.mapstruct.ap.internal.processor.DefaultVersionInformation.fromProcessingEnvironment(DefaultVersionInformation.java:95) at org.mapstruct.ap.internal.processor.DefaultModelElementProcessorContext.<init>(DefaultModelElementProcessorContext.java:50) at org.mapstruct.ap.MappingProcessor.processMapperElements(MappingProcessor.java:218) at org.mapstruct.ap.MappingProcessor.process(MappingProcessor.java:156) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.jetbrains.jps.javac.APIWrappers$1.invoke(APIWrappers.java:248) at org.mapstruct.ap.MappingProcessor.process(Unknown Source) at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794) at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:705) at com.

python-for循环的多种使用

🌳🌳🌳前言:本文简单总结了一下python中for循环的使用 目录 🌸for循环迭代字符串 🌸for打印数字 🌟注意for循环不能迭代数值类型 🍀for循环打印数字的话要借用range函数 🌸for循环可用来初始化列表 🍀简单的往列表里添加数据 🍀列表推导式 🌈python中for循环一般用来迭代字符串,列表,元组等。 当for循环用于迭代时不需要考虑循环次数,循环次数由后面的对象长度来决定。 🌸for循环迭代字符串 for循环可以把字符串里面的元素都依次取出来,自动赋值给变量i然后再执行循环体内的代码块 🍀print 里面的end可以设置每个值打印之后输出的字符串,默认是换行 🌸for打印数字 🌟注意for循环不能迭代数值类型 eg:int类型,123属于一个数,一个整体,算一个元素 🍀for循环打印数字的话要借用range函数 range函数可以取到一个范围内的整数,相比while要方便很多range(b) 默认从0开range(a,b) 左闭右开,包括左边不包括右边range(a,b,c) 从a到b的整数,每个c访问一次 🌰举个例子 ——range(b) 🌰举个例子 ——range(a,b) 🌰举个例子 ——range(a,b,c) 🌸for循环可用来初始化列表 存放大量数据,想要不停的接收数据,而且不想用那么多变量时可以用列表推导式 🍀简单的往列表里添加数据 🍀列表推导式 列表推导式可以快速生成一个列表,并筛选列表的值 🌰举个例子——筛选从0到20的偶数,不包括20 🌰举个例子——列表推导式+三目运算符 从0到10,如果为偶数就乘以100,如果为奇数就乘以10 🌰 列表推导式里面的for也可以迭代字符串 🍀自我总结:for的用法主要就是迭代,可以迭代列表、字符串、元组 ,但是不能迭代数值类型。 💬一起加油! ---------------------------END--------------------------- 题外话 感谢你能看到最后,给大家准备了一些福利! 感兴趣的小伙伴,赠送全套Python学习资料,包含面试题、简历资料等具体看下方。 👉CSDN大礼包🎁:全网最全《Python学习资料》免费赠送🆓!(安全链接,放心点击) 一、Python所有方向的学习路线 Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照下面的知识点去找对应的学习资源,保证自己学得较为全面。 二、Python兼职渠道推荐* 学的同时助你创收,每天花1-2小时兼职,轻松稿定生活费. 三、最新Python学习笔记 当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。 四、实战案例 纸上得来终觉浅,要学会跟着视频一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。 👉CSDN大礼包🎁:全网最全《Python学习资料》免费赠送🆓!(安全链接,放心点击) 若有侵权,请联系删除

全面了解SpringBoot拦截器

在本文中,我们将详细介绍SpringBoot中的拦截器,包括拦截器的概念、作用、实现方式、执行顺序、生命周期以及高级应用。最后,我们还将探讨拦截器的性能优化策略和常见问题。 1. 拦截器的概念和作用 1.1 什么是拦截器 拦截器(Interceptor)是一种特殊的组件,它可以在请求处理的过程中对请求和响应进行拦截和处理。拦截器可以在请求到达目标处理器之前、处理器处理请求之后以及视图渲染之前执行特定的操作。拦截器的主要目的是在不修改原有代码的情况下,实现对请求和响应的统一处理。 1.2 拦截器的作用 拦截器可以用于实现以下功能: 权限控制:拦截器可以在请求到达处理器之前进行权限验证,从而实现对不同用户的访问控制。日志记录:拦截器可以在请求处理过程中记录请求和响应的详细信息,便于后期分析和调试。接口幂等性校验:拦截器可以在请求到达处理器之前进行幂等性校验,防止重复提交。数据校验:拦截器可以在请求到达处理器之前对请求数据进行校验,确保数据的合法性。缓存处理:拦截器可以在请求处理之后对响应数据进行缓存,提高系统性能。 1.3 拦截器与过滤器的区别 拦截器和过滤器都可以实现对请求和响应的拦截和处理,但它们之间存在以下区别: 执行顺序:过滤器在拦截器之前执行,拦截器在处理器之前执行。功能范围:过滤器可以对所有请求进行拦截,而拦截器只能对特定的请求进行拦截。生命周期:过滤器由Servlet容器管理,拦截器由Spring容器管理。使用场景:过滤器适用于对请求和响应的全局处理,拦截器适用于对特定请求的处理。 2. SpringBoot中的拦截器实现 2.1 实现HandlerInterceptor接口 要在SpringBoot中实现拦截器,首先需要创建一个类并实现HandlerInterceptor接口。HandlerInterceptor接口包含以下三个方法: preHandle:在请求到达处理器之前执行,可以用于权限验证、数据校验等操作。如果返回true,则继续执行后续操作;如果返回false,则中断请求处理。postHandle:在处理器处理请求之后执行,可以用于日志记录、缓存处理等操作。afterCompletion:在视图渲染之后执行,可以用于资源清理等操作。 以下是一个简单的拦截器实现示例: public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { System.out.println("preHandle: " + request.getRequestURI()); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { System.out.println("postHandle: " + request.getRequestURI()); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { System.

手把手教你如何开通GitHub Copilot并且在vscode中使用

很多小伙伴应该已经知道Copilot的鼎鼎大名了,也有一些白嫖怪白嫖了3个月免费试用期后找不到续费的渠道,今天就给大家献上一篇续费/开通Copilot的文章; 1.首先登录git: git; 以及fomepay 2.点击头像->Copilot; 然后选择月付或者年付;如果长久使用建议年份能便宜$20(一个星期的超级豪华猪脚饭啊); 3.然后填写信息 4.最关键的一步 打开此链接(fomepay​​​​​​​) 可以用手机号或者邮箱注册的 至于为什么使用这家因为上一次我就使用他家的卡,开通了Copilot;今天是续费一下 然后我看推荐瞎选了一张卡 这里我得吐槽一下1次只能冲800块软妹币 注意:你要用多少就冲多少,不要重多了到时候不用这个站点的卡了就亏大发了 随便填名字就行了(不用实名、个人信息点个赞) 这一步是需要支付密码的(一开始会强制要求你设置) 注意: cvc/cvv不要暴露!!! 日期格式: 01/28 = 2028年01;以此类推 拿到信息后我们就可以在Copilot上填信息了 注意: cvc/cvv不要暴露!!! 至此支付成功 打开vscode 扩展搜索:GitHub Copilot 点击install 点击右下角Copilot图标然后登录git就ok啦 然后Copilot就会更具你的注释、部分帮忙写代码啦,以后搬砖都比别人快(滑稽) 最后在说一句:用多少冲多少,用的时候在开卡、充值

一文带你理解Python的dataclass装饰器

@dataclass 是 Python dataclasses 模块中的一个 decorator。当使用 @dataclass 装饰器时,它会自动生成一些特殊方法,包括: _ _ init _ _:用于初始化字段的构造函数_ _ repr _ _:对象的字符串表示_ _ eq _ _:对象之间的相等比较_ _ hash _ _:使对象可用作字典键(如果值是可哈希的) 除了上述列出的方法之外,@dataclass 装饰器还有两个重要的属性。 Order(顺序):如果为 True(默认为 False),将生成 [__lt__()](<https://docs.python.org/3/reference/datamodel.html#object.__lt__>)、[__le__()](<https://docs.python.org/3/reference/datamodel.html#object.__le__>)、[__gt__()](<https://docs.python.org/3/reference/datamodel.html#object.__gt__>) 和 [__ge__()](<https://docs.python.org/3/reference/datamodel.html#object.__ge__>) 方法;即 @dataclass(order=True)。Immutability(不可变性):通过使用 frozen=True 参数,可以使字段变为不可变;即 @dataclass(frozen=True)。 简而言之,@dataclass 装饰器的主要目标是简化类的创建。 dataclass 装饰器的优势 使用 dataclass 装饰器有几个优势: 减少样板代码:通过自动生成常见特殊方法,减少类所需的样板代码。可读性:通过使代码更简洁,集中在数据表示上,提高了代码的可读性。默认值:可以直接在类定义中为属性提供默认值,减少了显式 __init__() 方法的需求。不可变性:通过将 @dataclass 与 frozen=True 选项结合使用,可以创建不可变的数据类,确保实例在创建后无法修改。 用法 from dataclasses import dataclass @dataclass class Person: name: str age: int 在这个例子中,Person 类被注解为 @dataclass,并声明了两个字段(name 和 age)。__init__()、__repr__()、__eq__() 和 __hash__() 方法会自动生成。下面是如何使用每个生成的方法的解释:

python 标准库random生成随机数

当前版本: Python 3.8.4 文章目录如下 1. random的特点 2. random的用法 2.1. 随机整数 2.2. 随机小数 2.3. 随机元素 2.4. 随机字符串 1. random的特点 random 提供了生成伪随机数的功能,可以用于各种随机相关的操作,如生成随机数、洗牌、选择随机元素等。常用的内置方法如下: 【随机整数】 import random random.randint(x, y) # x~y之间的随机整数 random.randrange(start, stop[, step]) # 指定范围内的随机整数,可指定起始值、终止值和步长。 【随机浮点数】 import random random.random() # 0~1随机浮点数 random.uniform(x, y) # x~y之间的随机浮点数 【随机元素】 import random random.choice(seq) # 序列中随机选择一个元素 random.shuffle(seq) # 随机打乱序列中的元素的顺序 2. random的用法 2.1. 随机整数 随机整数一般通过 randint 或 randrange 来获取,它们的范围由平台位数决定: 32位范围:(-2^31) ~ (2^31 - 1) # -2147483648 ~ 2147483647 64位范围:(-2^63) ~ (2^63 - 1) # -9223372036854775808 ~ 9223372036854775807 常用的 randint 语法:

Node.js身份验证实践:Express-JWT和JSON Web Token的用法

目录 🎉前言 🎉准备工作 🎉实现生成token 🎉配置token校验 🎉完成获取用户信息接口 🎉配置校验错误的中间件 🎉总结 🎉前言 在构建Node.js应用时,安全性是一个至关重要的方面。本博客旨在解决如何在Express框架中实现令牌生成的问题,使用express-jwt和jsonwebtoken这两个流行的库来确保你的应用程序在身份验证方面具有强大的安全性。 token的作用 身份验证(Authentication): 证明身份: Token 用于证明用户的身份。当用户通过用户名和密码进行登录后,服务器会颁发一个 Token 给客户端。客户端在后续的请求中携带这个 Token,服务器通过验证 Token 来确认用户的身份,而不需要再次提供用户名和密码。这种方式避免了在每个请求中传输敏感的用户名和密码。无状态性: Tokens 可以使系统实现无状态的身份验证,因为每次请求都包含了足够的信息(Token)来识别和验证用户,而不需要在服务器端保存用户的登录状态。 授权(Authorization): 访问控制: Token 用于授权用户对特定资源的访问权限。服务器在验证用户身份后,生成包含权限信息的 Token,并将其返回给客户端。客户端在后续请求中携带 Token,服务器通过解析 Token 中的权限信息来确定用户是否被授权访问请求的资源。减轻服务器压力: 使用 Token 进行授权可以减轻服务器的负担,因为服务器无需在每个请求中都重新验证用户的身份和权限,而只需验证 Token 的有效性。 总的来说,Token在身份验证和授权方面提供了一种安全、高效的机制。通过使用 Token,可以实现无状态的身份验证、提高系统的安全性,同时减轻服务器的压力,提高系统的性能。 🎉准备工作 构建express应用,安装需要用到的库 npm i express npm i express-jwt npm i jsonwebtoken express-jwt 是用于在 Express 应用程序中验证 JSON Web Tokens (JWT) 的中间件。它可以帮助你确保只有经过身份验证的用户才能访问受保护的路由或资源。 jsonwebtoken 是用来生成客户端需要的token 搭建出基本的express应用 const express = require('express') const app = express() app.listen(3000, console.

Python 因果推断(下)

六、2007-2009 年大衰退期间加拿大就业市场上白人女性名字的溢价 原文:causal-methods.github.io/Book/6%29_The_Premium_of_Having_a_White_Female_Name_in_the_Canadian_Job_Market_During_the_Great_Recession_2007_2009.html 译者:飞龙 协议:CC BY-NC-SA 4.0 Vitor Kamada 电子邮件:econometrics.methods@gmail.com 最近更新:2020 年 9 月 15 日 我重新分析了 Oreopoulos(2011)的实验数据,并发现在 2007-2009 年大萧条期间,在加拿大的就业市场中,拥有白人女性名字是有优势的。白人女性在 2009 年 2 月至 9 月之间的回电率比白人男性高出 8%。考虑到白人男性在不同的回归规范下的回电率约为 10%,这一效应的幅度是相当高的。 Oreopoulos(2011)发现,英文名字的回电率为 15.7%,而印度、巴基斯坦、中国和希腊名字的回电率为 6%。我认为他的主要发现在很大程度上是由白人女性驱动的。我发现,在 2009 年 2 月至 9 月的大萧条最严重时期,拥有白人男性名字与印度、中国和希腊男性名字相比,并没有太多优势。 我使用了 Oreopoulos(2011)的数据集。每一行是发送给多个多伦多和蒙特利尔地区职业的简历。 import numpy as np import pandas as pd pd.set_option('precision', 3) # Data from Oreopoulos (2011) path = "https://github.com/causal-methods/Data/raw/master/" df = pd.read_stata(path + "oreopoulos.dta") df.head(5) 公司 ID职业类型name_ethnicity额外证书名字语言技能资格认证参考法律列出的资格认证…说话技能社交能力写作能力秋季数据中国人印度人英国人巴基斯坦人中加人相同经验0-3行政加拿大0.0JillWilson0.00.00.00.00.0…70.050.067.02.0NaNNaNNaNNaNNaNNaN1-3行政印度0.0PanavSingh0.00.00.00.00.0…70.050.067.02.0NaNNaNNaNNaNNaNNaN2-3行政印度0.0RahulKaur0.00.00.01.01.0…70.050.067.02.0NaNNaNNaNNaNNaNNaN3-3行政中国0.0雷丽0.01.01.00.01.0…70.050.067.02.0NaNNaNNaNNaNNaNNaN4-4行政印度0.0MayaKumar1.00.00.00.00.0…80.070.065.02.0NaNNaNNaNNaNNaNNaN 5 行×31 列 # Transform the variable of interest in % df["

【Java-JDK】JDK 的安装与环境变量的配置:Windows & Linux

【Java-JDK】JDK的安装与环境变量的配置:Windows & Linux 1)Windows安装JDK1.1.下载JDK1.1.安装JDK1.2.JDK环境配置1.3.验证环境变量是否配置成功 2)Linux安装JDK2.1.下载JDK2.2.安装JDK2.3.JDK环境配置2.4.验证环境变量配置是否成功 1)Windows安装JDK 1.1.下载JDK (1)下载地址 https://www.oracle.com/java/technologies/downloads/#jdk19-windows (2)根据电脑的系统选择64位的版本进行下载 1.1.安装JDK (1)双击安装包后点击下一步 (2)可以自行更改安装路径 1.2.JDK环境配置 (1)找到高级系统设置 (2)打开环境变量 (3)配置环境变量 (4)配置Path (5)点击2次确定,不然配置会失效 1.3.验证环境变量是否配置成功 (1) 按住Window+R ,输入cmd (2)验证并确定配置成功 2)Linux安装JDK 2.1.下载JDK (1)下载地址 https://www.oracle.com/java/technologies/downloads/#jdk19-linux (2)将安装包上传至服务器中 2.2.安装JDK (1)解压安装包 tar -zxvf jdk-8u341-linux-x64.tar.gz (2)查看解压是否成功,如果解压成功进入目录查看解压后的内容 ls jdk-8u341-linux-x64 2.3.JDK环境配置 (1)编辑/etc/profile vim /etc/profile (2)配置环境变量 export JAVA_HOME=/home/jinqi/local/JDK/jdk1.8.0_341 export JRE_HOME=/home/jinqi/local/JDK/jdk1.8.0_341/jre export CLASS_PATH=.:$JAVA_HOME/lib:$JRE_HOME/lib export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin 注意: 环境变量中的JAVA_HOME与JRE_HOME目录要与自己安装的目录保持一致 2.4.验证环境变量配置是否成功 java -version

macOS上使用x11转发运行Linux GUI软件——XQuartz

原因 这次要在mac上运行Linux GUI程序的原因还是蛮复杂的 我本来在学校有一台电脑吗,然后配置还不错,一直开着机,可以离线下载,开虚拟机用Linux,什么的都蛮方便的,而且很重要的是可以在寒假期间,可以远程到那台电脑上上知网,看看论文打打比赛都蛮方便的。15号回的家,一直用的都挺好的。 但是就很无语,学校校园网需要认证登陆,因为我从发15号到29号已经满了14天了吧,然后就被踢下来了,我的电脑就不能联网了,然后导致了我就不能远程到我的电脑来使用了。 学校早都放假了,老师教职工也都放假了,没有人能帮我联网了,这该怎么办呢,可是急死我了 但是我后来突然想到,虽然我不能远程到我的电脑了,但是学校里还有常年开着的服务器啊,而服务器和我的电脑都在一个内网内,那我岂不是可以先远程到服务器上,然后再使用服务器远程到我的电脑,然后使用RDP远程操作我的电脑登录网络? 虽然说电脑不能联网了,但是他获取的IPv4地址是不会变的,内网资源还是可以访问我的电脑的。 但是有一个很大的问题,只是我们实验室的服务器装的是Linux,然后Linux的GUI实在是不会用,向日葵安装的还是命令行版本,根本就不能远程到我的电脑,这该怎么办呢? 不过我之前使用xshell的时候,每次在xshell打开jupyterlab的时候,都会弹出很多对话框,问要不要使用xmanager转发x11请求? 我当时就很好奇,什么是x11请求呢,后来了解了一下,原来Linux上的GUI都是通过一个叫X Window System实现的,转发x11请求的意思就是可以将GUI界面转发到SSH客户端上,让它不只是SSH的cli界面,而是拥有了GUI界面。 后来搜索了一下,原来x11转发了以后,就像是微软的RDP Remote App一样,就是就像是客户端上原生的App一般,用起来感觉体验还是很不错的,(其实也有点像是Parallel Desktop的融合模式) 然后了解了一下,Linux下虽然没有Microsoft官方的RDP客户端,但是也有很多可以用的第三方RDP客户端,可以帮助我连接到我的PC。 有这些Linux上可用的RDP Cliet: RemminaGnome-connections 我搜了一下感觉还不错的就是这两个,特别是Remmina,感觉用户界面比较友好,支持的协议也很多。 最重要的是他支持网络级别的身份验证,这个真的很重要,因为我根本不可能在电脑上关闭网络级别的身份验证。 所以我就需要在这台Linux服务器上使用x11转发,让我能够远程到我的电脑进行校园网认真登录。 我的环境 客户端 MacBook Air(M1, 2020)macOS Sonoma 14.3(23D56) 服务端 Dell PowerEdge C4140Ubuntu 20.04 LTS Desktop With Gnome Desktop 注意!!! 服务器是有Gnome桌面的,没有的话您可能要考虑去安装一个桌面环境。 另外似乎现在的GUI的兼容性对于X Server来说兼容性比较好,使用Wayland作为桌面环境的,应该大概率是不能正常工作的 在macOS下使用x11转发运行Linux GUI App 安装x11客户端 macOS的自带的终端不支持x11请求,所以我们要下载一个软件,叫做XQuartz,直接官网下载就行 XQuartz官网 这软件还挺不错的,支持Intel和Apple Silicon 安装直接一路下一步就行 安装完了还得去注销一下当前用户,记得保存好文件,关掉Apps 配置XQuartz 安装完了这个软件,应该会默认放在启动器里面的系统工具,找不到的可以去找一下或者使用聚焦搜索,打开它 打开这个软件,应该是一个终端,键入Command + ,打开设置,在设置里打开这个选项:Allow connections from network clients,应该是允许互联网上的连接请求吧,我也不懂 打开后就在XQuartz里面使用ssh连接你的服务器主机了 连接服务器主机 使用SSH连接主机,就和一般命令行链接一样,不过记得加一个-X或者-Y的参数,表示允许X11连接转发。 一般情况下是使用-X这个参数就够了,不过,似乎某些高级3D应用程序,比如Maya,Blender这种软件会无法正常运行,所以就使用-Y这个参数来放宽安全政策。 你的命令可能是这样的:

MySql-学生成绩管理系统

前言 暑假的时候学习过这个 MySql 数据库,然后学校这个学期居然开了这门课程,那就做一个学生成绩管理系统来练一练手吧。在这里做一个简单的练习记录。 需求分析 SQL 编写 新建数据库 为该数据库建表 INSERT INTO 数据 创建索引 创建视图 创建触发器 创建存储过程 SQL 查询进行调试 结语 完整代码如下 -- 1. 新建数据库 drop database studentManage; CREATE DATABASE studentManage; use studentManage; -- 2. 创建表 -- 创建班级表 CREATE TABLE classes ( class_id INT PRIMARY KEY, -- 班级ID,作为主键 class_name VARCHAR(50) -- 班级名称,最大长度为50个字符 ); -- 插入班级数据 INSERT INTO classes (class_id, class_name) VALUES (0, '尖子班'); INSERT INTO classes (class_id, class_name) VALUES (1, '垃圾班'); INSERT INTO classes (class_id, class_name) VALUES (2, '垃圾班'); INSERT INTO classes (class_id, class_name) VALUES (3, '废物班'); INSERT INTO classes (class_id, class_name) VALUES (4, '废物班'); INSERT INTO classes (class_id, class_name) VALUES (5, '脑残班'); -- 创建学生表 CREATE TABLE students ( student_id INT PRIMARY KEY NOT NULL, -- 学生ID,作为主键,不允许为空 name VARCHAR(50), -- 姓名,最大长度为50个字符 class_id INT, -- 班级ID age INT, -- 年龄 FOREIGN KEY (class_id) REFERENCES classes(class_id) -- 外键关联到班级表的班级ID ); -- 插入学生数据 INSERT INTO students (student_id, name, class_id, age) VALUES (1, '王八', 5, 19); INSERT INTO students (student_id, name, class_id, age) VALUES (2, '王一', 1, 20); INSERT INTO students (student_id, name, class_id, age) VALUES (3, '小六', 0, 18); INSERT INTO students (student_id, name, class_id, age) VALUES (4, '王五', 2, 19); INSERT INTO students (student_id, name, class_id, age) VALUES (5, '赵六', 3, 20); INSERT INTO students (student_id, name, class_id, age) VALUES (6, '小七', 4, 18); -- 创建教师表 CREATE TABLE teachers ( teacher_id INT PRIMARY KEY NOT NULL, -- 教师ID,作为主键,不允许为空 teacher_name VARCHAR(50) -- 教师姓名,最大长度为50个字符 ); -- 插入教师数据 INSERT INTO teachers (teacher_id, teacher_name) VALUES (1, '陈老师'); INSERT INTO teachers (teacher_id, teacher_name) VALUES (2, '杨老师'); INSERT INTO teachers (teacher_id, teacher_name) VALUES (4, '何老师'); INSERT INTO teachers (teacher_id, teacher_name) VALUES (4, '刘老师'); INSERT INTO teachers (teacher_id, teacher_name) VALUES (5, '陈老师'); INSERT INTO teachers (teacher_id, teacher_name) VALUES (6, '周老师'); -- 创建课程表 CREATE TABLE courses ( course_id INT PRIMARY KEY NOT NULL, -- 课程ID,作为主键,不允许为空 course_name VARCHAR(50), -- 课程名称,最大长度为50个字符 teacher_id INT, -- 教师ID FOREIGN KEY (teacher_id) REFERENCES teachers(teacher_id) -- 外键关联到教师表的教师ID ); -- 插入课程数据 INSERT INTO courses (course_id, course_name, teacher_id) VALUES (100, '英语', 1); INSERT INTO courses (course_id, course_name, teacher_id) VALUES (101, '语文', 2); INSERT INTO courses (course_id, course_name, teacher_id) VALUES (102, '数学', 3); INSERT INTO courses (course_id, course_name, teacher_id) VALUES (103, '生物', 4); INSERT INTO courses (course_id, course_name, teacher_id) VALUES (104, '物理', 5); INSERT INTO courses (course_id, course_name, teacher_id) VALUES (105, '化学', 6); -- 创建成绩表 CREATE TABLE scores ( student_id INT, -- 学生ID course_id INT, -- 课程ID score INT, -- 分数 FOREIGN KEY (student_id) REFERENCES students(student_id), -- 外键关联到学生表的学生ID FOREIGN KEY (course_id) REFERENCES courses(course_id) -- 外键关联到课程表的课程ID ); -- 插入成绩数据 INSERT INTO scores (student_id, course_id, score) VALUES (1, 1, 92); INSERT INTO scores (student_id, course_id, score) VALUES (2, 1, 8); INSERT INTO scores (student_id, course_id, score) VALUES (3, 1, 5); INSERT INTO scores (student_id, course_id, score) VALUES (4, 1, 0); INSERT INTO scores (student_id, course_id, score) VALUES (5, 1, 8); INSERT INTO scores (student_id, course_id, score) VALUES (6, 1, 7); INSERT INTO scores (student_id, course_id, score) VALUES (1, 2, 100); INSERT INTO scores (student_id, course_id, score) VALUES (2, 2, 8); INSERT INTO scores (student_id, course_id, score) VALUES (3, 2, 5); INSERT INTO scores (student_id, course_id, score) VALUES (4, 2, 2); INSERT INTO scores (student_id, course_id, score) VALUES (5, 2, 8); INSERT INTO scores (student_id, course_id, score) VALUES (6, 2, 7); INSERT INTO scores (student_id, course_id, score) VALUES (1, 1, 100); INSERT INTO scores (student_id, course_id, score) VALUES (2, 2, 1); INSERT INTO scores (student_id, course_id, score) VALUES (3, 3, 7); INSERT INTO scores (student_id, course_id, score) VALUES (4, 4, 10); INSERT INTO scores (student_id, course_id, score) VALUES (5, 5, 10); INSERT INTO scores (student_id, course_id, score) VALUES (6, 6, 60); INSERT INTO scores (student_id, course_id, score) VALUES (1, 1, 100); INSERT INTO scores (student_id, course_id, score) VALUES (2, 2, 22); INSERT INTO scores (student_id, course_id, score) VALUES (3, 3, 71); INSERT INTO scores (student_id, course_id, score) VALUES (4, 4, 20); INSERT INTO scores (student_id, course_id, score) VALUES (5, 5, 30); INSERT INTO scores (student_id, course_id, score) VALUES (6, 6, 40); INSERT INTO scores (student_id, course_id, score) VALUES (1, 1, 100); INSERT INTO scores (student_id, course_id, score) VALUES (2, 2, 14); INSERT INTO scores (student_id, course_id, score) VALUES (3, 3, 72); INSERT INTO scores (student_id, course_id, score) VALUES (4, 4, 11); INSERT INTO scores (student_id, course_id, score) VALUES (5, 5, 11); INSERT INTO scores (student_id, course_id, score) VALUES (6, 6, 62); INSERT INTO scores (student_id, course_id, score) VALUES (1, 1, 100); INSERT INTO scores (student_id, course_id, score) VALUES (2, 2, 12); INSERT INTO scores (student_id, course_id, score) VALUES (3, 3, 73); INSERT INTO scores (student_id, course_id, score) VALUES (4, 4, 14); INSERT INTO scores (student_id, course_id, score) VALUES (5, 5, 15); INSERT INTO scores (student_id, course_id, score) VALUES (6, 6, 66); -- 3.

Mac 安装 RabbitMQ

一般来说,安装分为两种方式: 1. 下载 RabbitMQ 源文件,解压源文件之后进行安装。 2. 通过 brew 命令安装。在这里,推荐使用 brew 来安装,非常强大的 Mac 端包管理工具。 一、brew 命令安装Mac安装 RabbitMQ 1、安装 erlang # 终端输入 brew install erlang 2、安装 rabbitmq # 终端输入 brew install rabbitmq 3、配置 RabbitMQ 环境变量 # 终端输入 vi ~/.bash_profile 复制 # 添加配置 终端输入 vim ~/.bash_profile export RABBIT_HOME=/usr/local/Cellar/rabbitmq/3.12.12 export PATH=$PATH:$RABBIT_HOME/sbin # 更新配置 终端输入 source ~/.bash_profile 4、安装 RabiitMQ 的可视化监控插件 # 终端输入 sudo sbin/rabbitmq-plugins enable rabbitmq_management 二、Mac 后台启动 RabbitMQ 1、后台启动 # 终端输入 sudo rabbitmq-server -detached 2、查看状态

spring boot 使用 Kafka

一、Kafka作为消息队列的好处 高吞吐量:Kafka能够处理大规模的数据流,并支持高吞吐量的消息传输。 持久性:Kafka将消息持久化到磁盘上,保证了消息不会因为系统故障而丢失。 分布式:Kafka是一个分布式系统,可以在多个节点上运行,具有良好的可扩展性和容错性。 支持多种协议:Kafka支持多种协议,如TCP、HTTP、UDP等,可以与不同的系统进行集成。 灵活的消费模式:Kafka支持多种消费模式,如拉取和推送,可以根据需要选择合适的消费模式。 可配置性强:Kafka的配置参数非常丰富,可以根据需要进行灵活配置。 社区支持:Kafka作为Apache旗下的开源项目,拥有庞大的用户基础和活跃的社区支持,方便用户得到及时的技术支持。 二、springboot中使用Kafka 添加依赖:在pom.xml文件中添加Kafka的依赖,包括spring-kafka和kafka-clients。确保版本与你的项目兼容。 创建生产者:创建一个Kafka生产者类,实现Producer接口,并使用KafkaTemplate发送消息。 配置生产者:在Spring Boot的配置文件中配置Kafka生产者的相关参数,例如bootstrap服务器地址、Kafka主题等。 发送消息:在需要发送消息的地方,注入Kafka生产者,并使用其发送消息到指定的Kafka主题。 创建消费者:创建一个Kafka消费者类,实现Consumer接口,并使用KafkaTemplate订阅指定的Kafka主题。 配置消费者:在Spring Boot的配置文件中配置Kafka消费者的相关参数,例如group id、auto offset reset等。 接收消息:在需要接收消息的地方,注入Kafka消费者,并使用其接收消息。 处理消息:对接收到的消息进行处理,例如保存到数据库或进行其他业务逻辑处理。 三、使用Kafka pom中填了依赖 <dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> <version>2.8.1</version> </dependency> <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka-clients</artifactId> <version>2.8.1</version> </dependency> 创建生产者:创建一个Kafka生产者类,实现Producer接口,并使用KafkaTemplate发送消息。 import org.apache.kafka.clients.producer.*; import org.springframework.beans.factory.annotation.Value; import org.springframework.kafka.core.KafkaTemplate; import org.springframework.stereotype.Component; @Component public class KafkaProducer { @Value("${kafka.bootstrap}") private String bootstrapServers; @Value("${kafka.topic}") private String topic; private KafkaTemplate<String, String> kafkaTemplate; public KafkaProducer(KafkaTemplate<String, String> kafkaTemplate) { this.kafkaTemplate = kafkaTemplate; } public void sendMessage(String message) { Producer<String, String> producer = new KafkaProducer<>(bootstrapServers, new StringSerializer(), new StringSerializer()); try { producer.