springboot整合activemq,应答模式,消息重发机制,消息持久化

准备工作:

activemq的消息确认机制就是文档中说的ack机制有:

AUTO_ACKNOWLEDGE = 1    自动确认
CLIENT_ACKNOWLEDGE = 2    客户端手动确认   
DUPS_OK_ACKNOWLEDGE = 3    自动批量确认
SESSION_TRANSACTED = 0    事务提交并确认
INDIVIDUAL_ACKNOWLEDGE = 4    单条消息确认 activemq 独有

ACK模式描述了Consumer与broker确认消息的方式(时机),比如当消息被Consumer接收之后,Consumer将在何时确认消息。
对于broker而言,只有接收到ACK指令,才会认为消息被正确的接收或者处理成功了,通过ACK,可以在consumer(/producer)
与Broker之间建立一种简单的“担保”机制.

手动确认和单条消息确认需要手动的在客户端调用message.acknowledge()

消息重发机制RedeliveryPolicy 有几个属性如下:

 RedeliveryPolicy redeliveryPolicy= new RedeliveryPolicy();
	        //是否在每次尝试重新发送失败后,增长这个等待时间
	        redeliveryPolicy.setUseExponentialBackOff(true);
	        //重发次数,默认为6次   这里设置为10次
	        redeliveryPolicy.setMaximumRedeliveries(10);
	        //重发时间间隔,默认为1秒
	        redeliveryPolicy.setInitialRedeliveryDelay(1);
	        //第一次失败后重新发送之前等待500毫秒,第二次失败再等待500 * 2毫秒,这里的2就是value
	        redeliveryPolicy.setBackOffMultiplier(2);
	        //是否避免消息碰撞
	        redeliveryPolicy.setUseCollisionAvoidance(false);
	        //设置重发最大拖延时间-1 表示没有拖延只有UseExponentialBackOff(true)为true时生效
	        redeliveryPolicy.setMaximumRedeliveryDelay(-1);

以下情况会导致消息重发:
1.在使用事务的Session中,调用rollback()方法;
2.在使用事务的Session中,调用commit()方法之前就关闭了Session;
3.在Session中使用CLIENT_ACKNOWLEDGE签收模式或者INDIVIDUAL_ACKNOWLEDGE模式,并且调用了recover()方法。
可以通过设置ActiveMQConnectionFactory来定制想要的再次传送策略。

需要注意的是:使用手动签收模式,如果客户端没有调用message.acknowledge()方法是不会立刻重发消息的,只有当前Coustomer重启时才能重新接受消息

spring boot 整合activemq 需要jar

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-activemq</artifactId>
		</dependency>

因自己的需求,自己在默认的配置类中增加自己的配置

ActiveMQ4Config如下:

package com.zyc.activemq;

import javax.jms.Queue;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.RedeliveryPolicy;
import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.core.JmsTemplate;

@EnableJms  
@Configuration  
public class ActiveMQ4Config {  

	@Bean
	public Queue queue(){
		return new ActiveMQQueue("queue1");
	}

	@Bean
	public RedeliveryPolicy redeliveryPolicy(){
	        RedeliveryPolicy  redeliveryPolicy=   new RedeliveryPolicy();
	        //是否在每次尝试重新发送失败后,增长这个等待时间
	        redeliveryPolicy.setUseExponentialBackOff(true);
	        //重发次数,默认为6次   这里设置为10次
	        redeliveryPolicy.setMaximumRedeliveries(10);
	        //重发时间间隔,默认为1秒
	        redeliveryPolicy.setInitialRedeliveryDelay(1);
	        //第一次失败后重新发送之前等待500毫秒,第二次失败再等待500 * 2毫秒,这里的2就是value
	        redeliveryPolicy.setBackOffMultiplier(2);
	        //是否避免消息碰撞
	        redeliveryPolicy.setUseCollisionAvoidance(false);
	        //设置重发最大拖延时间-1 表示没有拖延只有UseExponentialBackOff(true)为true时生效
	        redeliveryPolicy.setMaximumRedeliveryDelay(-1);
	        return redeliveryPolicy;
	}
    @Bean
    public ActiveMQConnectionFactory activeMQConnectionFactory (@Value("${activemq.url}")String url,RedeliveryPolicy redeliveryPolicy){  
        ActiveMQConnectionFactory activeMQConnectionFactory =  
                new ActiveMQConnectionFactory(
                       "admin",
                        "admin",
                        url);
        activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);
        return activeMQConnectionFactory;
    }
    
    @Bean
    public JmsTemplate jmsTemplate(ActiveMQConnectionFactory activeMQConnectionFactory,Queue queue){
    	JmsTemplate jmsTemplate=new JmsTemplate();
    	jmsTemplate.setDeliveryMode(2);//进行持久化配置 1表示非持久化,2表示持久化
    	jmsTemplate.setConnectionFactory(activeMQConnectionFactory);
    	jmsTemplate.setDefaultDestination(queue); //此处可不设置默认,在发送消息时也可设置队列
    	jmsTemplate.setSessionAcknowledgeMode(4);//客户端签收模式
    	return jmsTemplate;
    }
    
    //定义一个消息监听器连接工厂,这里定义的是点对点模式的监听器连接工厂
    @Bean(name = "jmsQueueListener")
    public DefaultJmsListenerContainerFactory jmsQueueListenerContainerFactory(ActiveMQConnectionFactory activeMQConnectionFactory) {
        DefaultJmsListenerContainerFactory factory =
                new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(activeMQConnectionFactory);
        //设置连接数
        factory.setConcurrency("1-10");
        //重连间隔时间
        factory.setRecoveryInterval(1000L);
        factory.setSessionAcknowledgeMode(4);
        return factory;
    }

}  
消费者如下:使用异步监听(使用监听器形式)
package com.zyc.activemq.consumer;

import javax.jms.JMSException;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class Consumer {

	private final static Logger logger = LoggerFactory
			.getLogger(Consumer.class);
	
	@JmsListener(destination = "queue1", containerFactory = "jmsQueueListener")
	public void receiveQueue(final TextMessage text, Session session)
			throws JMSException {
		try {
			logger.debug("Consumer收到的报文为:" + text.getText());
			text.acknowledge();// 使用手动签收模式,需要手动的调用,如果不在catch中调用session.recover()消息只会在重启服务后重发
		} catch (Exception e) {	
			session.recover();// 此不可省略 重发信息使用
		}
	}
}
生产者如下:

package com.zyc.activemq.producer;

import javax.jms.Destination;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;

@Component
public class Producer {
	
	@Autowired
	private JmsTemplate jmsTemplate;
	/**
	 * 发送消息,estination是发送到的队列,message是待发送的消息
	 * @param destination
	 * @param message
	 */
	public void sendMessage(Destination destination, final String message) {
		System.out.println(jmsTemplate.getDeliveryMode());
		jmsTemplate.convertAndSend(destination, message);
	}
	/**
	 * 发送消息,message是待发送的消息
	 * @param message
	 */
	public void sendMessage(final String message) {
		System.out.println(jmsTemplate.getDeliveryMode());
			jmsTemplate.convertAndSend("queue1",message);
	}

}

application.properties配置文件如下:

spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

activemq.url=failover:(tcp://127.0.0.1:61616)
测试如下:如果不知道springboot junit 测试可参考 springboot junit测试

package com.zyc;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;
import com.zyc.activemq.producer.Producer;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)
public class ApplicationTest {

	@Autowired
	private Producer producer;
	@Test
	public void testActivemq(){
		producer.sendMessage("look this is a message==zycc==");
		while(true){}
	}
}

本文参考了

http://shift-alt-ctrl.iteye.com/blog/2020182

http://blog.csdn.net/varyall/article/details/49907995

  • 8
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
好的,我可以为您提供一个简单的示例。 首先,您需要在SpringBoot项目中添加ActiveMQ的依赖。在pom.xml文件中添加以下代码: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-activemq</artifactId> </dependency> ``` 然后,您需要在application.properties文件中配置ActiveMQ的连接信息,如下所示: ```properties spring.activemq.broker-url=tcp://localhost:61616 spring.activemq.user=admin spring.activemq.password=admin ``` 接下来,您需要创建一个消息队列,用于存储要发送的邮件信息。在SpringBoot中,可以使用JmsTemplate来发送消息。您可以在您的Java代码中注入JmsTemplate,然后使用它来发送邮件消息。以下是一个示例代码: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jms.core.JmsTemplate; import org.springframework.stereotype.Service; @Service public class EmailService { @Autowired private JmsTemplate jmsTemplate; public void sendEmail(String to, String message) { jmsTemplate.convertAndSend("email.queue", new Email(to, message)); } } ``` 在上面的代码中,我们注入了JmsTemplate,并使用它来发送一个Email对象到名为“email.queue”的消息队列中。 最后,您需要编写一个消息监听器,用于监听邮件队列中的消息,并实现邮件发送逻辑。以下是一个示例代码: ```java import org.springframework.jms.annotation.JmsListener; import org.springframework.stereotype.Component; @Component public class EmailListener { @Autowired private JavaMailSender mailSender; @JmsListener(destination = "email.queue") public void sendEmail(Email email) { SimpleMailMessage message = new SimpleMailMessage(); message.setTo(email.getTo()); message.setSubject("Test Email"); message.setText(email.getMessage()); mailSender.send(message); } } ``` 在上面的代码中,我们使用@JmsListener注解来监听名为“email.queue”的消息队列中的消息,并实现了邮件发送逻辑。 最后,您需要确保ActiveMQ服务器已经启动,然后运行您的SpringBoot应用程序即可。 希望这个示例对您有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值