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); } }