• JMS概述


    介绍

    Java Message Service是一组支持网络上主机间正式的消息通信的API, 它为Java应用程序提供了通用的消息协议以及消息服务。使用Jms可以创建,发送,读取消息。
    JMS主要的作用是提供异步通信,实现应用程序组件间的解耦,同时提高的系统的可靠性, 稳定性。

    消息通信模型

    P2P模型(Poing-to-Poing)

    在p2p模型中, 消息通信的实现依赖于消息队列,发送者,接收者。每条消息被发送到特定的队列之中, 队列会一直保存消息,直到消息被接收或者过期, p2p的特点如下:

    • 对于每一条消息只有一个消费者
    • 生产者,消费者对一条消息的处理没有时间上的同步要求
    • 不管消费者是否在运行, 生产者发送消息之后消费者在消息未过期的情况下可随时接收消息
    • 消费者接收完消息之后发送确认消息,确认消息已被接收。
    发布/订阅模型

    在发布/订阅模型中,一条消息通过一个主题(Topic)发送到所有的客户端,即订阅者。 发布者和订阅者是异步的, 并且可以自由向主题发布消息或订阅主题中的消息。 主题负责保存和传递消息。
    发布/订阅模型的特点如下:

    • 对于一条消息可以有多个订阅者,即多个消费者
    • 消费者只有在订阅主题之后才能获得发布到主题上的消息, 并且订阅者必须一直保持活跃以接收消息

    消息处理方式

    在JMS中,消息处理可以是同步的或者异步的。

    同步消息处理

    在同步消息处理中, 消费者或者订阅者通过调用receive()方法接收消息, receive()方法会一直阻塞, 指导收到消息或者超过指定的时间。

    异步消息处理

    在异步消息处理中,订阅者和消费者可以注册一个消息监听器, 类似于事件监听器,当消息到达之后, JMS Provide会通过调用消息监听器的onMessage()方法传递消息。

    JMS主要对象介绍

    • Connection Factories and Destination
    • Connections
    • Sessions
    • Message Producers
    • Message Consumers
    • Message listeners
    JMS Administered Objects

    Connection Factories
    可以通过connection factory 创建一个连接, 即在JMS提供者和客户端之间创建连接。 JMS客户端可以在JNDI中查找连接, 这个连接即为服务端和客户端之间的连接。通过这个连接, 客户端可以通过队列或主题的方式发送接收消息。

    QueueConnectionFactory queueConnFactory = (QueueConnectionFactory) initialCtx.lookup ("primaryQCF");
    Queue purchaseQueue = (Queue) initialCtx.lookup ("Purchase_Queue");
    Queue returnQueue = (Queue) initialCtx.lookup ("Return_Queue");
    

    Destination
    客户端可以通过指定destination来决定发送到哪条队列之上, 从而决定谁可以接收它。 JMS提供两种类型的destination, 队列(Queue)和主题(Topic)。

    QueueSession ses = con.createQueueSession (false, Session.AUTO_ACKNOWLEDGE);  //get the Queue object 
    Queue t = (Queue) ctx.lookup ("myQueue");  //create QueueReceiver 
    QueueReceiver receiver = ses.createReceiver(t);
    
    TopicSession ses = con.createTopicSession (false, Session.AUTO_ACKNOWLEDGE); // get the Topic object 
    Topic t = (Topic) ctx.lookup ("myTopic");  //create TopicSubscriber 
    TopicSubscriber receiver = ses.createSubscriber(t);
    
    Connection

    连接对象封装了服务端和客户端的连接, 它实现了Connection接口, 可通过ConnectionFactory对象创建连接,使用完之后可以关闭它。

    Connection connection = connectionFactory.createConnection();
    connection.close();
    
    JMS Session

    会话表示一个单线程的上下文用来发送或接收消息,通过会话可以创建生产者和消费者。 可以通过连接对象来创建会话

    Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    
    JMS Message Producer

    生产者即由会话创建的用来发送消息的对象, 它实现了MessageProducer接口。

    MessageProducer producer = session.createProducer(dest);
    MessageProducer producer = session.createProducer(queue);
    MessageProducer producer = session.createProducer(topic);
    producer.send(message);
    
    JMS Message Consumer

    消费者即由会话创建的用来接收消息的对象,它实现了MessageConsumer接口, 可以使用它来接收destionation, queue或topic中的消息( destination是一个通用表示消息中介的接口, queue和topic实现了destination接口)。

    MessageConsumer consumer = session.createConsumer(dest);
    MessageConsumer consumer = session.createConsumer(queue);
    MessageConsumer consumer = session.createConsumer(topic);
    
    JMS Message Listeners

    消息监听器是一个异步处理消息的对象, 它实现了MessageListener接口, 接口中有一个onMessage()方法用来定义处理动作, 通过在消费者上调用setMessageListener()方法来设置消息监听器。

    Listener myListener = new Listener();
    consumer.setMessageListener(myListener);
    

    JMS消息组成

    1. Message Header
      包含一系列属性被服务端和客户端用来发布及识别消息, 这些属性包括:
      – JMSDestination
      – JMSDeliveryMode
      – JMSMessageID
      – JMSTimestamp
      – JMSCorrelationID
      – JMSReplyTo
      – JMSRedelivered
      – JMSType
      – JMSExpiration
      – JMSPriority

    2. Message Properties
      应用程序可以创建,设置消息属性,这些属性是一系列键值对。 通过读取消息属性可以过滤消息, JMS也提供了一些预定义的服务端可以识别的消息属性, 这些属性是可选的。

    3. Message Body
      JMS预定义五种不同的消息体类型来发送或接收消息, 包括:

    • Text message : javax.jms.TextMessage对象, 代表文本消息
    • Object message: javax.jms.ObjectMessage对象, 代表java对象
    • Bytes message: javax.jms.BytesMessage对象, 代表二进制消息
    • Stream message: javax.jms.StreamMessage对象,代表java原生对象的集合
    • Map message: javax.jms.MapMessage对象,代表键值对

    JMS Template应用

    创建JMS Template
    @Bean
    public JmsTemplate createJMSTemplate() {
    
        SQSConnectionFactory sqsConnectionFactory = SQSConnectionFactory.builder()
                .withAWSCredentialsProvider(awsCredentialsProvider)
                .withEndpoint(endpoint)
                .withNumberOfMessagesToPrefetch(10).build();
    
        JmsTemplate jmsTemplate = new JmsTemplate(sqsConnectionFactory);
        jmsTemplate.setDefaultDestinationName(queueName);
        jmsTemplate.setDeliveryPersistent(false);
        return jmsTemplate;
    }
    
    发送消息
    public void sendMessage(final String message) {
    
    jmsTemplate.send(queueName, new MessageCreator() {
        @Override
        public Message createMessage(Session session) throws JMSException {
            return session.createTextMessage(message);
        }
    });
    }
    
    同步接收消息
    Message msg = jmsTemplate.receive("myQueue");
    
    异步接收消息

    异步处理消息, message listener container是必须的, 它用来绑定连接类工厂(connection factory), JMS Destination和message listener bean。 Spring有三种方式配置消息监听器: 实现javax.jms.MessageListener接口, 实现Spring的SessionAwareMessageListener(增加了对Jms Session的访问)和绑定一个POJO到Spring的MessageListenerAdapter类上。
    对于消息监听器容器, Spring提供了两种: DefaultMessageListenerContainer和SimpleMessageListenerContainer, 两者都允许指定数量的并发监听线程 ,且DefaultMessageListenerContainer允许和XA Transaction集成, 对于使用本地事务管理器和不需要基于可变负载的线程、会话、连接调整的简单消息传递应用, 使用SimpleMessageListenerContainer, 对于使用外部事务管理器或XA事务的消息传递应用, 使用DefaultMessageListenerContainer。

    @Bean
    public DefaultMessageListenerContainer jmsListenerContainer() {
    
        SQSConnectionFactory sqsConnectionFactory = SQSConnectionFactory.builder()
                .withAWSCredentialsProvider(new DefaultAWSCredentialsProviderChain())
                .withEndpoint(endpoint)
                .withAWSCredentialsProvider(awsCredentialsProvider)
                .withNumberOfMessagesToPrefetch(10).build();
    
        DefaultMessageListenerContainer dmlc = new DefaultMessageListenerContainer();
        dmlc.setConnectionFactory(sqsConnectionFactory);
        dmlc.setDestinationName(queueName);
    
        dmlc.setMessageListener(sqsListener);
    
        return dmlc;
    }
    

    实现MessageListener接口的监听器

    @Component
    public class SQSListener implements MessageListener {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(SQSListener.class);
    public void onMessage(Message message) {
        TextMessage textMessage = (TextMessage) message;
        try {
            LOGGER.info("Received message "+ textMessage.getText());
        } catch (JMSException e) {
            LOGGER.error("Error processing message ",e);
        }
    }
    }
    

    https://howtodoinjava.com/jms/jms-java-message-service-tutorial/
    https://egkatzioura.com/2016/02/27/aws-sqs-and-spring-jms-integration/
    https://blog.csdn.net/moonsheep_liu/article/details/6684948

  • 相关阅读:
    有关try..catch..finally处理异常的总结
    java中finally和return的执行顺序
    慢查询处理
    阿里云数据库配置文件
    在DEV c++ 中如何设置默认的代码模板
    「C语言」单链表/双向链表的建立/遍历/插入/删除
    使用VS.NET2019做为C++开发专用IDE
    Windows下通过SSH无密码连接Linux服务器
    海沧区磁盘扩容思路办法
    Rabbitmq异常排查
  • 原文地址:https://www.cnblogs.com/helloz/p/9311202.html
Copyright © 2020-2023  润新知