Java框架之spring 的 messaging

news2024/9/24 7:24:45

写在前面

本文看下spring message相关的内容。

1:Message?Messaging?

Message是消息的意思,是一个名词。而Messaging是一个动名词,是将消息发送出去的意思,因此,我们的消息系统是messaging system,而非message system,像我们经常使用的消息中间件activeMQ等,就是一个messaing system,即一个用来将消息接收并且发送的系统。同理,后文我们将要看到的JMS,也是Java messaging service。

2:为什么要有MQ

服务与服务之间,通过同步的方式调用不就行了吗?为什么非得创建MQ这么个东西呢?因为同步调用方式有如下的缺点:

1:服务与服务之间的调用关系呈网状,调用关系复杂,某个服务出现问题,会引起连锁反应,降低系统稳定性。
2:同步的调用方式,当出现大量线程阻塞等待时,会给服务器资源使用带来具体的压力,降低系统稳定性。

以上可以参考下图:

在这里插入图片描述

可以看到调用关系极其复杂,当有n个系统时,就会存在n*(n-1)/2条线,就像蜘蛛网一样,密密麻麻,我们在设计系统时一定要避免这种情况的方法。为了解决这些问题,就出现了消息中间件,通过提供如下的能力,解决了以上的问题:

1:同步转异步
2:削峰填谷

此时结构就变为下图:

在这里插入图片描述

这样,组件和组件之间不直接产生关联,而是通过消息中间件间接的产生关系,系统的连线也都到消息中间件,连线的个数也从原来的n*(n-1)/2减少为n,结构更加清晰,系统运维会变得更加容易维护。

3:JMS

无规矩不成方圆,在数据库操作领域jdk中有jdbc相关的规范接口,在日志领域有JCL,SLF4J 日志门面。自然的,对于消息中间件也需要这样一个规范,这也就是就是jdk中的JMS,java messaging service,Java消息服务,在JMS中定义了queue和topic的概念,其中queue是一种生产消费的模式,消息最终只会被一个消费者接收,topic是一种发布订阅模式,消息可以被所有的订阅者接收,如下图:

在这里插入图片描述

JMS规范最常见的实现就是activeMQ了,所以接下来我们也以activeMQ为例,来看下如何通过spring message模块的功能来收发消息。

4:spring messaging

[源码] (https://gitee.com/dongsir2020/dongshidaddy-labs-new/tree/master/jms/src/main/java/dongshi/daddy/springmessaging)。

spring messaging模块在spring源码中的位置如下图:

在这里插入图片描述

为了测试,首先我们需要安装activeMQ,在这里 下载对应操作系统的安装包,下载完毕之后就可以按照如下方式启动了:

在这里插入图片描述

我这里是直接双击win64/activemq.bat,运行,运行后访问http://localhost:9161/,默认是8161,因为我本地8161端口被占用了,所以修改成了9161,正常直接使用8161就行,之后点击Manage ActiveMQ broker就可以进入如下的界面:

在这里插入图片描述

接着我们来使用spring messaging来向其生产和消费消息,首先定义生产者xml,如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
    <context:component-scan base-package="dongshi.daddy.springmessaging"/>
    
    <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name = "brokerURL" value="tcp://localhost:61616" />
    </bean>
    
    <bean id="queue" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg value = "test.queue" />
    </bean>
    
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name = "connectionFactory" ref="connectionFactory" />
    </bean>
    
</beans>

接着定义生产者的类:

@Component
public class SendService {
    @Autowired
    JmsTemplate jmsTemplate;
    
    public void send(final Student user) {
        jmsTemplate.send("test.queue", new MessageCreator() {
            
            public Message createMessage(Session session) throws JMSException {
                return session.createObjectMessage(JSON.toJSONString(user));
            }
        });
    }
}

public class JmsSender {

    public static void main(String[] args) {
        Student student2 = Student.create();

        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:springjms-sender.xml");

        SendService sendService = (SendService) context.getBean("sendService");

        student2.setName("KK103");

        sendService.send(student2);

        System.out.println("send successfully, please visit http://localhost:8161/admin to see it");
    }

}

运行JmsSender后,查看activeMQ:

在这里插入图片描述

接着我们定义消费者消费消息,xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jms="http://www.springframework.org/schema/jms"
       xsi:schemaLocation="
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/jms 
            http://www.springframework.org/schema/jms/spring-jms-3.0.xsd">
    
    <context:component-scan base-package="dongshi.daddy.springmessaging"/>
    
    <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name = "brokerURL" value="tcp://localhost:61616" />
        <property name="trustAllPackages" value="true" />
    </bean>
    
    <bean id="queue" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg value = "test.queue" />
    </bean>
    
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name = "connectionFactory" ref="connectionFactory" />
    </bean>
    
    <jms:listener-container
            container-type="default"
            connection-factory="connectionFactory"
            acknowledge="auto">
        <jms:listener destination="test.queue" ref="jmsListener" method="onMessage"></jms:listener>
    </jms:listener-container>
    
</beans>

接收类:

@Component(value = "jmsListener")
public class JmsListener implements MessageListener {
    
    //收到信息时的动作
    @Override
    public void onMessage(Message m)  {
        ObjectMessage message = (ObjectMessage) m;
        try {
            System.out.println("收到的信息:" + message.getObject());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

public class JmsReceiver {
    
    public static void main( String[] args ) throws IOException {
        
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:springjms-receiver.xml");
        
        System.in.read();
        
        System.out.println("send successfully, please visit http://localhost:8161/admin to see it");
    }
    
}

运行JmsReceiver,console输出:

received message: {"id":102,"name":"KK103"}

在这里插入图片描述

这样就完成了消息的生产和消费了。

写在后面

参考文章列表

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

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

相关文章

SuperMap iServer 扩展账户信息合规度校验规则

作者&#xff1a;lisong 目录 功能简介配置文件详情扩展和配置流程 功能简介 SuperMap iServer 11i&#xff08;2023&#xff09; 新增了扩展账户信息合规度校验规则的能力&#xff0c;您可以灵活定制满足自身项目需求的用户名、密码合规度校验规则&#xff0c;用于校验您创建…

企业邮箱如何修改管理员密码

1、登录企业邮局&#xff0c;点击顶部“邮局管理”。在邮局管理中点击“组织与成员”,在用户列表中&#xff0c;点击“邮局管理员”&#xff08;postmaster&#xff09;。 2、在编辑用户中&#xff0c;点击“重置密码”,然后输入新的密码&#xff0c;保存即可。

java中的xxl-job-core完成定时任务的步骤

首先这个是基于docker的所以需要进行docker配置 1、先导入官方提供的SQL到虚拟机中mysql中 2、创建容器 docker run -e PARAMS"--spring.datasource.urljdbc:mysql://192.168.211.136:3306/xxl_job?useUnicodetrue&characterEncodingUTF-8&autoReconnecttrue&a…

2014年全国硕士研究生入学统一考试管理类专业学位联考数学试题——纯题目版

2014 年考研管理类联考数学真题 一、问题求解&#xff08;本大题共 15 小题&#xff0c;每小题 3 分&#xff0c;共 45 分&#xff09;下列每题给出 5 个选项中&#xff0c;只有一个是符合要求的&#xff0c;请在答题卡上将所选择的字母涂黑。 1.某部门在一次联欢活动中共设了 …

python接口自动化测试 - configparser配置文件解析器详细使用

configparser简介 ConfigParser模块已在Python 3中重命名为configparser该模块定义了ConfigParser类。 ConfigParser类实现一种基本的配置文件解析器语言&#xff0c;该语言提供的结构类似于 .ini 文件中的结构 Python自动化测试&#xff1a;手把手教你做60个实战项目&#xf…

设计模式(二十三)——解释器模式(Interpreter )

解释器模式&#xff08;Interpreter &#xff09; 实现了一个表达式接口&#xff0c;该接口解释一个特定的上下文 应用 编译器&#xff0c;正则表达式&#xff0c;SQL解析 实现 实现一个一位数的加法运算 public class Interpreter {public int add(String s){if (s.char…

代码复现:基于精英动态反向学习的增强型正余弦算法—EDOLSCA,可用于对比试验

代码复现&#xff1a;基于精英动态反向学习的增强型正余弦算法—EDOLSCA&#xff0c;可用于对比试验。 参考文献&#xff1a;Zhang L, Hu T, Yang Z, et al. Elite and dynamic opposite learning enhanced sine cosine algorithm for application to plat-fin heat exchanger…

带你用Python制作超级经典的2048游戏(文末赠书)

名字&#xff1a;阿玥的小东东 学习&#xff1a;Python、C/C 主页链接&#xff1a;阿玥的小东东的博客_CSDN博客-python&&c高级知识,过年必备,C/C知识讲解领域博主 目录 2048游戏Python实现 本期赠书 2048游戏Python实现 2048游戏是一款非常流行的益智游戏&#xff0…

vue-cli的Nuxt重构

我的博客用vuecli写的&#xff0c;SEO不忍直视。于是用Nuxt重构了代码&#xff0c;过程中踩了无数坑 一&#xff1a;body样式不生效 正常的body样式设置不能生效&#xff0c;需要在nuxt.config.js中配置 1、设置bodyAttrs的class属性&#xff0c;该属性值对应一个类名 2、该…

Unity 聚焦任意大小的物体

聚焦任意大小的物体 &#x1f371;效果&#x1f96a;食用方法 &#x1f371;效果 &#x1f96a;食用方法 &#x1f4a1;.安装Cinemachine &#x1f4a1;.把Assets/ZYF/Tools/Camera/Scene/FocusGo/FocusCtrl.prefab拖入场景 &#x1f4a1;.调用FocusCtrl.Focus(gameObject)即可…

《kafka 核心技术与实战》课程学习笔记(九)

客户端都有哪些不常见但是很高级的功能&#xff1f; 什么是 Kafka 拦截器&#xff1f; 拦截器基本思想就是允许应用程序在不修改逻辑的情况下&#xff0c;动态地实现一组可插拔的事件处理逻辑链。它能够在主业务操作的前后多个时间点上插入对应的“拦截”逻辑。Spring MVC 拦…

接口跨域问题

只要协议不同/端口号不同/域名不同都会导致跨域问题

深入浅出设计模式 - 中介者模式

博主介绍&#xff1a; ✌博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家✌ Java知识图谱点击链接&#xff1a;体系化学习Java&#xff08;Java面试专题&#xff09; &#x1f495;&#x1f495; 感兴趣的同学可以收…

C++之lambda表达式回调函数作为参数(一百四十)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

【python】matplotlib 绘制火山图、条形图

文章目录 火山图条形图 火山图 绘制火山图&#xff0c;输入是两个datafreme&#xff0c;行是样本名&#xff0c;列是基因名。使用T-test检验绘制基因表达情况。 def minmax_scale(data):import numpy as np# # 示例数据# data np.array([2, 4, 6, 8, 10])# 进行Min-Max标准化…

go并发编程之channel

目录 1.简介 2.channel类型 无缓冲区的channel 无缓冲区channel的创建 带缓冲区的channel 带缓冲区channel的创建 3.channel使用代码演示 4.获取channel中的值 ​编辑 5.单向channel 单向发送data&#xff0c;发送到channel中 单向接收&#xff0c;channel接收数据 6…

汇编的各种指令及使用方法

***************************************************************** 汇编中的符号 1.指令&#xff1a; 能够编译生成一条32位的机器码&#xff0c;且能被CPU识别和执行 2.伪指令&#xff1a;本身不是指令&#xff0c;编译器可以将其替换成若干条等效指令 3.伪操作&#xff1a…

Linux进程间通信——管道(下)

前文 一&#xff0c;什么是命名管道? 二&#xff0c;命名管道的基本原理 三&#xff0c;创建命名管道实现两个进程对写 四&#xff0c;匿名管道和命名管道的区别 总结 前文 上篇文章我们主要讲了匿名管道的定义以及基本原理&#xff0c;但是匿名管道有一个致命的缺陷&#…

HashSet、LinkedHashSet、TreeSet有什么区别

- HashSet、LinkedHashSet 和 TreeSet 都是 Set接口的实现类&#xff0c;都能保证元素唯一&#xff0c;并且都不是线程安全的。HashSet 的底层数据结构是哈希表&#xff08;基于 HashMap 实现&#xff09;&#xff0c;元素存入和取出顺序不一致。LinkedHashSet 的底层数据结构…

C++制作五子棋

正文 01 思路 我没有选择专业的五子棋棋型&#xff0c;用我自己的逻辑&#xff08;初高中玩五子棋的方法&#xff09;&#xff0c;去实现简单的人机对战。 首先因为要计算五子棋每一步的分数&#xff0c;那么你就要分析每一步形成的棋盘&#xff0c;以下图为例&#xff1a;…