JMS规范

ConnectionFactory 用于创建连接到消息中间件的连接工厂
Connection 代表了应用程序与消息服务器之间的通信链路(一个连接可以创建多个会话)
Destination 只消息发布和接受的地点,包括队列或主题
Session 表示一个单线程的上下文,用于发送和接受消息(所有会话都在一个线程中)
MessageConsumer 由会话创建,用于接受发送到目标的消息
MessageProducer 由会话创建,用于发送消息到目标
Message 由会话创建,是生成者/发布者和消费者/订阅者之间传送的对象,包括一个消息头,一组消息属性、一个消息体


 

支持的传输协议:AUTO、OpenWire、AMQP、Stomp、MQTT等
传输方式:VM、TCP(基于tcp的NIO)、SSL、UDP、Peer、Multicast、HTTP(S)
高级的传输协议:Failover、Fanout、Discover、ZeroConf

ActiveMQ 默认传输协议:OpenWire,且同时可支持配置多协议;

传输方式:默认TPC 端口61616  对外使用:SSL

也可以使用组合[NIO+SSL]方式:nio+ssl://192.168.1.2:61616

ActiveMQ Java示例

生产者:

public class Producer {
    public static void main(String[] args) {
        new ProducerThread("tcp://activemq.tony.com:61616", "queue1").start();
    }

    static class ProducerThread extends Thread {
        String brokerUrl;
        String destinationUrl;

        public ProducerThread(String brokerUrl, String destinationUrl) {
            this.brokerUrl = brokerUrl;
            this.destinationUrl = destinationUrl;
        }

        @Override
        public void run() {
            ActiveMQConnectionFactory connectionFactory;
            Connection conn;
            Session session;

            try {
                // 1、创建连接工厂
                connectionFactory = new ActiveMQConnectionFactory(brokerUrl);
                // 2、创建连接对象 connection
                conn = connectionFactory.createConnection();
                conn.start();
                // 3、创建会话 ,如果使用事务conn.createSession(true,Session.SESSION_TRANSACTED);
                session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
                // 4、创建点对点发送的目标
                 Destination destination = session.createQueue(destinationUrl);
                // 5、创建生产者消息
                MessageProducer producer = session.createProducer(destination);
                // 设置生产者的模式,有两种可选 持久化 / 不持久化
                producer.setDeliveryMode(DeliveryMode.PERSISTENT);
                // 6、创建一条文本消息
                String text = "Hello world!";
                TextMessage message = session.createTextMessage(text);
                for (int i = 0; i < 1; i++) {
                    // 7、发送消息
                    producer.send(message);
                }
                // 8、 关闭连接 如果存在事务 则进行事务提交或者事务回滚,session.commit() 或者session.rollback();
                session.close();
                conn.close();
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }
    }
}

 

conn.createSession方法:参1 是否支持事务,参2 Session接口中值,如果参1 支持事务 则参2 默认是SESSION_TRANSACTED;

 

其中Session接口有四种方式:

    int AUTO_ACKNOWLEDGE = 1;  //自动确认,客户端发送和接收消息不需要做额外的工作
    int CLIENT_ACKNOWLEDGE = 2;//客户端确认。客户端接收到消息后,必须调用javax.jms.Message的acknowledge方法。jms服务器才会删除消息。 
    int DUPS_OK_ACKNOWLEDGE = 3; //允许副本的确认模式。一旦接收方应用程序的方法调用从处理消息处返回,会话对象就会确认消息的接收;而且允许重复确认
    int SESSION_TRANSACTED = 0;

消息重发策略:

1、consumer通过事务 未能正常消费,则server会对consumer进行重发;

2、通过重发策略

   // 创建队列重发策略
   RedeliveryPolicy queuePolicy = new RedeliveryPolicy();
   queuePolicy.setInitialRedeliveryDelay(0); // 初始重发延迟时间,单位:毫秒
   queuePolicy.setRedeliveryDelay(5000); // 第一次以后的延迟时间
   queuePolicy.setUseExponentialBackOff(false);// 是否以指数递增的方式增加超时时间
   queuePolicy.setMaximumRedeliveries(3); // 最大重发次数,从0开始计数,为-1则不使用最大次数
   .....
   // 设置重发策略
   connectionFactory.setRedeliveryPolicy(queuePolicy);

 

 

消费者:

    @Override
    public void run() {
        ActiveMQConnectionFactory connectionFactory;
        Connection conn;
        Session session;
        MessageConsumer consumer;

        try {
            // brokerURL http://activemq.apache.org/connection-configuration-uri.html
            // 1、创建连接工厂
            connectionFactory = new ActiveMQConnectionFactory(this.brokerUrl);
            // 2、创建连接对象
            conn = connectionFactory.createConnection();
            conn.start(); // 一定要启动
            // 3、创建会话(可以创建一个或者多个session)
            session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
            // 4、创建点对点接收的目标,queue - 点对点
            Destination destination = session.createQueue(destinationUrl);

            // 5、创建消费者消息 http://activemq.apache.org/destination-options.html
            consumer = session.createConsumer(destination);

            // 6、接收消息(没有消息就持续等待)
            Message message = consumer.receive();
            if (message instanceof TextMessage) {
                System.out.println("收到文本消息:" + ((TextMessage) message).getText());
            } else {
                System.out.println(message);
            }

            consumer.close();
            session.close();
            conn.close();
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }

 

ActiveMQ SpringBoot示例

此时需要配置文件进行配置:

spring.activemq.broker-url=tcp://activemq.tony.com:61616
spring.activemq.user=admin
spring.activemq.password=admin

 

//生产者
@SpringBootApplication
public class Producer {

    @Autowired
    private JmsTemplate jmsTemplate;

    @PostConstruct
    public void init() {
        jmsTemplate.convertAndSend("queue1", "Hello Spring 4");
    }

    public static void main(String[] args) {
        SpringApplication.run(Producer.class, args);
    }
}


//消费者
@SpringBootApplication
@EnableJms
public class Consumer {

    @JmsListener(destination = "queue1")
    public void receive(String message) {
        System.out.println("收到消息:" + message);
    }

    public static void main(String[] args) {
        SpringApplication.run(Consumer.class, args);
    }
}

 

ActiveMQ SpringBoot 通过Bean自动注入示例

@Configuration
@EnableJms
public class JmsConfiguration {

    /**
     * 连接工厂
     * @param brokerUrl
     * @param userName
     * @param password
     * @return
     */
    @Bean
    public ConnectionFactory connectionFactory(@Value("${spring.activemq.broker-url}") String brokerUrl,
                   @Value("${spring.activemq.user}") String userName,
                   @Value("${spring.activemq.password}") String password) { return new ActiveMQConnectionFactory(userName, password, brokerUrl); } /** * 队列模式的监听容器 * @param connectionFactory * @return */ @Bean public JmsListenerContainerFactory<?> jmsListenerContainerFactoryQueue(ConnectionFactory connectionFactory) { DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory(); bean.setConnectionFactory(connectionFactory); return bean; } /** * topic 模式监听容器 * @param connectionFactory * @return */ @Bean public JmsListenerContainerFactory<?> jmsListenerContainerFactoryTopic(ConnectionFactory connectionFactory) { DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory(); bean.setConnectionFactory(connectionFactory); bean.setPubSubDomain(true); return bean; } /** * 队列模板 * @param connectionFactory * @return */ @Bean public JmsTemplate jmsTemplateQueue(ConnectionFactory connectionFactory) { return new JmsTemplate(connectionFactory); } /** * 发布订阅模板 * * @param connectionFactory * @return */ @Bean public JmsTemplate jmsTemplatePublish(ConnectionFactory connectionFactory) { JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory); jmsTemplate.setPubSubDomain(true); return jmsTemplate; } }

 相应的生产者和消费者:

@SpringBootApplication
public class Producer {

    @Autowired
    private JmsTemplate jmsTemplatePublish;

    @Autowired
    private JmsTemplate jmsTemplateQueue;

    @PostConstruct
    public void send() {
        // 队列模式发送
        jmsTemplatePublish.convertAndSend("topic1", "Hello Spring topic 1");

        // 发布订阅模式发送
        jmsTemplateQueue.send("queue1", new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                MapMessage message = session.createMapMessage();
                message.setString("msg", "Hello Spring xxxx");
                return message;
            }
        });
    }

    public static void main(String[] args) {
        SpringApplication.run(Producer.class, args);
    }
}



@SpringBootApplication
public class Consumer {

    @JmsListener(destination = "queue1", containerFactory = "jmsListenerContainerFactoryQueue")
    public void receiveQueue(Message message) throws JMSException {
        if (message instanceof TextMessage) {
            System.out.println("收到文本消息:" + ((TextMessage) message).getText());
        } else if (message instanceof ActiveMQMapMessage) {
            System.out.println("收到Map消息:" + ((ActiveMQMapMessage) message).getContentMap());
        } else {
            System.out.println(message);
        }
    }

    @JmsListener(destination = "topic1", containerFactory = "jmsListenerContainerFactoryTopic")
    public void receiveTopic(String message) {
        System.out.println("收到订阅消息:" + message);
    }

    public static void main(String[] args) {
        SpringApplication.run(Consumer.class, args);
    }
}

 

posted on 2019-09-11 21:27  gudicao  阅读(116)  评论(0编辑  收藏  举报