SpringBoot·消息通信
消息一部通信-消息异步通信的实现方式与场景简介
- jms
- spring的消息驱动模型
- activemq
- rabbitmq
- kafka
JMS
JMS是一系列的接口及相关语义的集合,通过这些接口和和其中的方法,JMS客户端如何去访问消息系统,完成创建、发送、接收和读取企业消息系统中消息。
在JMS之前,每一家MOM厂商都用专有API为应用程序提供对其产品的访问,通常可用于许多种语言,其中包括Java语言。JMS通过MOM为Java程序提供了一个发送和接收消息的标准的、便利的方法。用JMS编写的程序可以在任何实现JMS标准的MOM上运行。
JMS可移植性的关键在于:JMS API是由Sun作为一组接口而提供的。提供了JMS功能的产品是通过提供一个实现这些接口的提供者来做到这一点的。开发人员可以通过定义一组消息和一组交换这些消息的应用程序,建立JMS应用程序,实现异步通讯。
Java Message Service是由Sun开发的,它为 Java程序提供一种访问企业消息系统的方法。
企业消息系统,即面向消息的中间件(MOM),提供了以松散耦合的灵活方式集成应用程序的一种机制。
它们提供了基于存储和转发的应用程序之间的异步数据发送,即应用程序彼此不直接通信,而是与作为中介的MOM 通信。
MOM提供了有保证的消息发送,应用程序开发人员无需了解远程过程调用(PRC)和网络/通信协议的细节。ActiveMQ正是MOM中优秀的一员。
JMS的目标
JMS从提出以来,致力于完成如下几个目标:
定义一组消息公用概念和实用工具。
所有Java应用程序都可以使用JMS中定义的API去完成消息的创建、接收与发送
,任何实现了JMS标准的MOM都可以作为消息的中介,完成消息的存储转发。
最大化消息应用程序的可移植性
MOM提供了有保证的消息发送,应用程序开发人员无需了解远程过程调用(PRC)
和网络/通信协议的细节,提供了程序的可移植性。
最大化降低应用程序与应用系统之间的耦合度
由于MOM的存在,各个应用程序只关心和MOM之间如何进行消息的接收与发送,而无需关注MOM的另一边,
其他程序是如何接收和发送的。 ## rabbitmq的安装配置
1. 先下载并安装erlang
原因:RabbitMQ服务端代码是使用并发式语言Erlang编写的 ,安装RabbitMQ的前提是安装Erlang。
官网地址: https://www.erlang.org/downloads
配置环境变量:
ERL_HOME 系统环境变量 E:\java_tools\RabbitMQ_tools\erl-24.0
PATH: %ETL_HONE%\bin;
校验环境变量是否配置成功
win+r -> 输入 cmd -> 输入 erl -> 回车
2. 下载RabbitMQ
官网地址: https://www.rabbitmq.com/install-windows.html
新建系统变量:变量名 RABBITMQ_SERVER
变量值 E:\java_tools\RabbitMQ_tools\RabbitMq_service\rabbitmq_server-3.9.15(RabbitMQ Server安装目录)
PATH: %RABBITMQ_SERVER%\sbin;
安装激活 rabbitmq-plugins
#打开CMD工具
Win+r -> 输入 cmd
#切换到D盘
E:
#指定到rabbit安装目录
cd E:\java_tools\RabbitMQ_tools\RabbitMq_service\rabbitmq_server-3.9.15
#安装rabbitmq-plugins可视化工具,如果提示 fail,则安装失败
rabbitmq-plugins enable rabbitmq_management
#启动rabbitmq-service
rabbitmq-service.bat start
#关闭服务
rabbitmq-service.bat stop
##重启服务
net stop RabbitMQ && net start RabbitMQ
3. 创建用户,密码,绑定角色
在浏览器输入地址:http://localhost:15672 输入默认账号:guest
密码:guest,就能进入RabbitMQ界面了。
查看已有用户及用户的角色:
rabbitmqctl.bat list_users
新增用户
rabbitmqctl.bat add_user username password
rabbitmqctl.bat add_user ldc 123
赋权
rabbitmqctl.bat set_user_tags username administrator
rabbitmqctl.bat set_user_tags ldc administrator
访问地址
http://localhost:15672
设置用户权限
rabbitmqctl set_permissions -p VHostPath User ConfP WriteP ReadP
查看(指定hostpath)所有用户的权限信息
rabbitmqctl list_permissions [-p VHostPath]
查看指定用户的权限信息
rabbitmqctl list_user_permissions User
清除用户的权限信息
rabbitmqctl clear_permissions [-p VHostPath] User
RabbitMQ 使用
定义队列、交换机、队列与交换机绑定
@Configuration
public class DirectRabbitConfig {
//队列 起名:TestDirectQueue
@Bean
public Queue TestDirectQueue() {
// durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
// exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
// autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
// return new Queue("TestDirectQueue",true,true,false);
//一般设置一下队列的持久化就好,其余两个就是默认false
return new Queue("fristQueue",true);
}
//Direct交换机 起名:TestDirectExchange
@Bean
DirectExchange TestDirectExchange() {
// return new DirectExchange("TestDirectExchange",true,true);
return new DirectExchange("Exchange",true,false);
}
//绑定 将队列和交换机绑定, 并设置用于匹配键:TestDirectRouting
@Bean
Binding bindingDirect() {
return BindingBuilder.bind(TestDirectQueue()).to(TestDirectExchange()).with("key_k");
}
// 新建一个空的交换机
@Bean
DirectExchange lonelyDirectExchange() {
return new DirectExchange("lonelyDirectExchange");
}
}
接受消息放到MQ中
从MQ的管理平台上可以查看还没有消费的消息条数
http://localhost:15672/
@RestController
public class SendMessageController {
@Autowired
RabbitTemplate rabbitTemplate; //使用RabbitTemplate,这提供了接收/发送等等方法
@GetMapping("/sendmsg")
public String sendDirectMessage() {
String messageId = String.valueOf(UUID.randomUUID());
String messageData = "test message, hello!";
String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
Map<String,Object> map=new HashMap<>();
map.put("messageId",messageId);
map.put("messageData",messageData);
map.put("createTime",createTime);
//将消息携带绑定键值:TestDirectRouting 发送到交换机TestDirectExchange
rabbitTemplate.convertAndSend("Exchange", "key_k", map);
return "ok";
}
}
消费消息-打印到控制台或存放到数据库中
消息消费后MQ管理平台中就会清除记录
http://localhost:15672/
@Component
@RabbitListener(queues = "TestDirectQueue")//监听的队列名称 TestDirectQueue
public class DirectReceiver {
@RabbitHandler
public void process(Map testMessage) {
System.out.println("DirectReceiver消费者收到消息 : " + testMessage.toString());
}
}