【发布时间】:2015-12-20 22:38:42
【问题描述】:
我知道这听起来像听过 1000 次,但我不这么认为 我真的找不到解决方案:
使用普通 ejb 我可以使用确认模式来确认() 手动留言。如果我不这样做,它会重新交付。我做了这个 在过去,它运作良好。
使用 Spring JMS 我遇到的问题似乎是我要么 可以将重新传递设置为仅在出现异常时处理 扔或根本不扔。
如何实现和ejb一样?
我的问题是:如果消息被确认,我不想要 即使发生异常,也要重新交付。
【问题讨论】:
我知道这听起来像听过 1000 次,但我不这么认为 我真的找不到解决方案:
使用普通 ejb 我可以使用确认模式来确认() 手动留言。如果我不这样做,它会重新交付。我做了这个 在过去,它运作良好。
使用 Spring JMS 我遇到的问题似乎是我要么 可以将重新传递设置为仅在出现异常时处理 扔或根本不扔。
如何实现和ejb一样?
我的问题是:如果消息被确认,我不想要 即使发生异常,也要重新交付。
【问题讨论】:
“sessionAcknowledgeMode”设置为“AUTO_ACKNOWLEDGE”(默认):该模式依赖于容器:对于DefaultMessageListenerContainer,表示在监听器执行前自动确认消息,出现异常不重发,其他监听不重发执行中断。对于 SimpleMessageListenerContainer,这意味着在监听器执行后自动确认消息,在抛出用户异常的情况下不会重新传递,但在监听器执行期间 JVM 死机的情况下可能会重新传递。为了始终如一地安排任何容器变体的重新交付,请考虑“CLIENT_ACKNOWLEDGE”模式或 - 最好 - 将“sessionTransacted”设置为“true”。 “sessionAcknowledgeMode”设置为“DUPS_OK_ACKNOWLEDGE”:在 (DefaultMessageListenerContainer) 期间或 (SimpleMessageListenerContainer) 侦听器执行后不久进行延迟消息确认;如果抛出用户异常,则不会重新交付,但如果 JVM 在侦听器执行期间死亡,则可能会重新交付。为了始终如一地安排任何容器变体的重新交付,请考虑“CLIENT_ACKNOWLEDGE”模式或 - 最好 - 将“sessionTransacted”设置为“true”。 “sessionAcknowledgeMode”设置为“CLIENT_ACKNOWLEDGE”:监听器执行成功后自动消息确认;在引发用户异常以及其他侦听器执行中断(例如 JVM 死亡)的情况下,尽最大努力重新交付。 “sessionTransacted”设置为“true”:成功监听执行后的事务确认;在引发用户异常以及其他侦听器执行中断(例如 JVM 死机)的情况下保证重新交付。
Spring JMS 框架为消息确认公开了上层抽象。用户只需要关心发生用户异常时是否重新投递消息的场景。
所以,要注意消息监听容器工厂的bean,并相应配置jms选项。
【讨论】:
感谢您的回复。但是,我完全是这样做的, 除了我使用 Spring 3 和注释配置。问题 不是接收而是确认。如果我使用交易 与否,似乎消息是自动确认的,而 接收。
我尝试了直接扩展 MessageListener 并遵循 .. 注意到作品。
public class JMSListener implements SessionAwareMessageListener<TextMessage> {
...
@Override
public void onMessage(TextMessage message, Session session) {
...
}
}
这样我就可以看到会话设置。例如。 session.getAcknowledgeMode() 传递客户端确认和 session.getTransacted() 传递 true 或 false 取决于我设置的内容。但似乎没有任何效果。 无论如何,该消息似乎已被确认。
spring的CLIENT_ACKNOWLEDGE的java doc也有区别 和杰。对于春天,写着:
“CLIENT_ACKNOWLEDGE”:监听执行成功后自动消息确认;抛出异常时不重新投递。
对于jee有写:
CLIENT_ACKNOWLEDGE 使用这种确认模式,客户端通过调用消息的确认方法来确认已消费的消息。
对我来说,这可能是原因吗?但如果真的是这样(我 简直不敢相信)它会使 spring 无法处理消息?
【讨论】:
我们可以根据您的要求使用 spring 框架的 DefaultMessageListenerContainer。
请从 Spring 中找到以下文档:
以类似于 EJB 世界中的消息驱动 Bean (MDB) 的方式, 消息驱动的 POJO (MDP) 充当 JMS 消息的接收者。这 一个限制(但另见下文讨论 MDP 上的 MessageListenerAdapter 类)是它必须实现 javax.jms.MessageListener 接口。另请注意,在 您的 POJO 将在多个线程上接收消息的情况, 确保您的实现是线程安全的很重要。
http://docs.spring.io/spring/docs/2.5.x/reference/jms.html#jms-asynchronousMessageReception
以下是我在方法上添加了确认()方法的代码sn-p。
JMS 监听器类:
public class MyProjectJMSListener implements MessageListener {
public void onMessage(Message message) {
try {
message.acknowledge();
//Business logic to be added
}
catch (JMSException ex) {
throw new RuntimeException(ex);
}
}
}
spring-jms-config.xml
<bean id="messageListener" class="com.myproj.MyProjectJMSListener" />
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/> <!-- connectionFactory bean class to be added -->
<property name="destination" ref="my.jms.destination"/>
<property name="messageListener" ref="messageListener" />
</bean>
【讨论】: