有一个类'MyConsumer'从队列接收消息并处理它们。有两个要求:
我尝试使用spring-jms,使用监听器 - 容器支持,但找不到符合第一个要求的解决方案。
我的代码:
<amq:queue id="destination" physicalName="org.springbyexample.jms.test"/>
<amq:connectionFactory id="jmsFactory" brokerURL="tcp://localhost:11111"/>
<bean id="jmsConsumerConnectionFactory"
class="org.springframework.jms.connection.SingleConnectionFactory"
p:targetConnectionFactory-ref="jmsFactory"/>
<bean id="jmsConsumerTemplate" class="org.springframework.jms.core.JmsTemplate"
p:connectionFactory-ref="jmsConsumerConnectionFactory"
p:defaultDestination-ref="destination"/>
<bean id="jmsMessageListener" class="test.MyConsumer"/>
<bean id="errorHandler" class="test.MyErrorHandler"/>
<jms:listener-container container-type="default"
connection-factory="jmsConsumerConnectionFactory"
error-handler="errorHandler"
acknowledge="client">
<jms:listener destination="org.springbyexample.jms.test" ref="jmsMessageListener"/>
</jms:listener-container>
班级MyConsumer
:
@Override
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("!!!!!!!!! get message: " + textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
if (theNumberOfMessageIs(3)) {
throw new RuntimeException("something is wrong");
}
}
您可能会注意到acknowledge
中的listener-container
为client
,实际上它有3个值:
我尝试了所有这些,但没有一个符合我的要求。我的测试场景:
auto
:
MyConsumer将在收到每条消息后确认,无论是否抛出异常
client
:
MyConsumer仅在onMessage
没有抛出异常时才会确认。对于第3条消息,它抛出异常,队列中将有一条未消息的消息。但是当它获得第4条消息并且不会抛出异常时,队列中的第3条消息将会消失
transacted
:
如果在MyConsumer中抛出异常,则不会确认该消息并多次重新传递。之后,消息从队列中消失
但它们都不符合要求1.
我想知道:如果我需要寻找除Spring-jms之外的其他解决方案,或者我的用法不正确?
答案 0 :(得分:0)
auto
DefaultMessageListenerContainer
实际上是为交易设计的 - 使用auto,正如您所发现的那样,消息始终被确认。您可以使用SimpleMessagseListenerContainer
,它可以按您的意愿工作,但它有其他限制;请参阅JavaDocs。
client
这就是JMS在你知道#4时的工作方式,#3也自动被激活 - 请参阅Message
JavaDocs。客户端模式用于减少ack流量(例如,每10条消息执行一次)。
transacted
这是代理的一个功能,你可以配置AMQ在重试一段时间后将坏消息发送到死信队列。
您需要一些过程将消息从DLQ移回主队列以便稍后重试(可能在重启时初始化期间)。