activemq 事务--遇到异常始终回滚

 

转自:https://blog.csdn.net/lsm135/article/details/74945116

1. 启用消息事务
<property name="sessionTransacted" value="true"/>




2. 当消息在消费的时候,如果用户程序抛出Exception,则消息会回滚重传(mq里面的未消费消息数目不变), 
spring 的activemq默认最多重传6次, 超过6次,即使抛出了异常,这个消费仍然被消费不可回滚。
jms.redeliveryPolicy.maximumRedeliveries=6(默认)
我们可以设置brokerURL里面的jms.redeliveryPolicy.maximumRedeliveries=-1
-1表示可以无限次重传,0表示不重传。


注意中间要用 html转移符 &amp;     (就是url查询字符串里的&字符)

3.消息队列回滚的触发--程序本身运行异常,比如数据库操作异常,如果自己用程序去检查数据库更新条数,如果小于1,程序可以人为编写代码,人为

抛出一个RuntimeException. 这两种情况都能触发消息的rollback

如在onMesssage()里,或者内部嵌套的方法里

throw new RuntimeException("Update DB failed.");

最终配置文件如下

appContext.xml

 
  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <beans xmlns="http://www.springframework.org/schema/beans"

  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"

  4. xsi:schemaLocation="

  5. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

  6. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

  7.  
  8. <import resource="mybatisContext.xml" />

  9. <import resource="shardingContext.xml" />

  10.  
  11. <!-- 配置JMS连接工厂 -->

  12. <!-- 测试环境 -->

  13. <bean id="jmsFactory" class="org.apache.activemq.spring.ActiveMQConnectionFactory">

  14. <property name="brokerURL"

  15. value="failover:(tcp://10.0.0.9:61616)?randomize=false&timeout=3000&initialReconnectDelay=100&jms.useAsyncSend=true&jms.redeliveryPolicy.maximumRedeliveries=-1" />

  16. </bean>

  17. <!-- 配置JMS模版 -->

  18. <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">

  19. <property name="connectionFactory">

  20. <!-- lets wrap in a pool to avoid creating a connection per send -->

  21. <bean class="org.springframework.jms.connection.SingleConnectionFactory">

  22. <property name="targetConnectionFactory">

  23. <ref local="jmsFactory" />

  24. </property>

  25. </bean>

  26. </property>

  27. </bean>

  28.  
  29. <!-- MQ监听者 -->

  30. <bean id="smsSendForMQListener"

  31. class="org.springframework.jms.listener.DefaultMessageListenerContainer">

  32. <property name="connectionFactory">

  33. <ref bean="jmsFactory" />

  34. </property>

  35. <property name="destinationName">

  36. <value>DistributePics</value>

  37. </property>

  38. <property name="messageListener">

  39. <ref bean="saveListener" />

  40. </property>

  41. <!-- mq事务控制,如果抛异常了就回滚消息 -->

  42. <property name="sessionTransacted" value="true"/>

  43.  
  44. </bean>

  45.  
  46. <!-- Spring MVC -->

  47. <context:component-scan base-package="com.x.service"></context:component-scan>

  48. <context:component-scan base-package="com.x.controller.**"></context:component-scan>

  49. <context:component-scan base-package="com.x.listener"></context:component-scan>

  50. <context:component-scan base-package="com.x.spring"></context:component-scan>

  51. </beans>

java程序如下:

 
  1. package com.x.imgapp.listener;

  2.  
  3. import java.util.concurrent.Future;

  4.  
  5. import javax.jms.JMSException;

  6. import javax.jms.Message;

  7. import javax.jms.MessageListener;

  8. import javax.jms.ObjectMessage;

  9. import javax.jms.BytesMessage;

  10.  
  11. import org.springframework.stereotype.Component;

  12.  
  13. import com.x.imgapp.common.model.MsgBean;

  14. import com.x.imgapp.concurrent.AppExecutor;

  15. import com.x.imgapp.concurrent.MoveThread;

  16.  
  17. import org.apache.activemq.command.ActiveMQBytesMessage;

  18. import org.apache.activemq.util.ByteSequence;

  19. import org.slf4j.Logger;

  20. import org.slf4j.LoggerFactory;

  21.  
  22. /**

  23. *

  24. * @author frank.liu

  25. *

  26. */

  27. @Component("saveListener")

  28. public class SaveDBListener implements MessageListener {

  29. private static final Logger logger = LoggerFactory.getLogger(SaveDBListener.class);

  30. private static Long receiveCount = 0L;

  31.  
  32. @Override

  33. public void onMessage(Message message) {

  34. logger.info("Step into onMessage()------------------------------->");

  35. ActiveMQBytesMessage msg = (ActiveMQBytesMessage) message;

  36. ByteSequence sequence = msg.getContent();

  37. String msgStr = new String(sequence.data);

  38. //

  39. // Future<Integer> future = AppExecutor.getExecutor().submit(new MoveThread(msgStr));

  40. logger.info("receiveCount:{}", ++receiveCount);

  41. throw new RuntimeException("Update DB failed.");

  42. }

  43. }

  44.  

猜你喜欢

转载自blog.csdn.net/cyywxy/article/details/81189222