JMS-如何将消息发送回客户端?

JMS-如何将消息发送回客户端?,jms,objectoutputstream,Jms,Objectoutputstream,这是我的客户端代码: 公共类ABCServlet扩展了HttpServlet{ protected void doGet(HttpServletRequest request, HttpServletResponse response){ //do blah blah String msg = null; java.io.OutputStream os = response.getOutputStream(); java.io.ObjectOutputStre

这是我的客户端代码:

公共类ABCServlet扩展了HttpServlet{

protected void doGet(HttpServletRequest request,
                 HttpServletResponse response){
//do blah blah
String msg = null;

java.io.OutputStream os = response.getOutputStream();
java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream(os);
oos.writeObject(msg);
msg = null;
oos.flush();
oos.close();
}
我不知道如何使用上述代码启动我的侦听器-

public class ABCListener implements MessageListener {

@Override
public void onMessage(Message arg0) {
 AbstractJDBCFacade façade = null;
 try{
    façade = something;
    throw new UserException();
 }catch(UserException ex){
    log.error("ABC Exception " + ex);
 }
配置:

<bean id="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">....

<bean id="jmsQueue" class="org.springframework.jndi.JndiObjectFactoryBean">

<bean id="listenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer102">
。。。。
我有3个问题: 1.如果不显式地将其放在队列中,如何调用侦听器? 2.当onMessage方法抛出UserException时,我不想记录日志,而是想将消息传递给客户端。我该怎么做?
3.为什么有人会使用JndiObjectFactoryBean而不是ActiveMQ…

JMS在设计上被认为是异步和单向的,甚至是“同步的”使用consumer的receive方法的jms将在内部转变为创建一个新的临时队列。这里我们来谈谈它的单向性的第二点。jms队列应该是单向的,这就是为什么它被称为点到点().当然,从技术上讲,通过一些舞蹈,你将能够实现你想要的,但这是一种不好的做法,因为你需要过滤,这也会导致性能下降

为了让这件事情快速运行,最好的方法是只有一个逻辑接收器(当然,您可以为一个接收器使用并发消费程序,但这应该是一个逻辑消费程序,而不需要过滤消息)

  • 如果不显式地将其放在队列中,如何调用侦听器
  • 侦听器只有在消息到达队列时才会被调用。这是使其按预期工作的唯一方法

    通常有两种类型的消息使用模型:推送(也称为事件驱动的使用)和轮询在代理中的某个位置注册,然后,当代理在某个队列中接收到新消息时,它会执行侦听器的方法。在轮询模型的另一端,消费者会自行处理接收消息的事宜。因此,每隔一段时间,它会来到代理并检查队列中是否有新消息

    推送模式:

    投票模式:

  • 当onMessage方法抛出UserException时,我不想记录日志,而是想将消息传递给客户机。我该怎么做
  • 这是一个非常糟糕的做法。当然,从技术上讲,您可以通过肮脏的技巧实现这一点,但这不是使用jms的正确方法。当onMessage引发异常时,消息将不会从队列中获取(当然,如果您没有重新配置acknowledge mods或使用其他技巧)。因此,解决问题的最佳方法是对消息和死信队列()使用重新传递限制。如果系统在一些尝试后无法处理消息(重新传递限制正好显示了这一点),则代理将消息从队列中移除,并将其发送到所谓的死信队列,其中所有消息都失败(从代理的角度)消息被存储。然后客户端可以读取该队列并决定如何处理该消息

    在amq中:

    如果要使用所谓的“同步”JMS中的功能,实际上没有办法使用死信队列或类似的smth,那么实际上您可以在客户端上使用consumer.recieve方法。但是在这种情况下,您应该在每条消息上发送响应。如果成功,您可以发送一条消息,如果失败,则发送错误消息。因此,客户端将能够理解什么是g继续。但我不认为您需要如此巨大的开销,因为实际上您只需要失败消息。在这种情况下,您还必须注意适当的接收超时

  • 为什么有人会使用JndiObjectFactoryBean而不是ActiveMQ
  • 这是因为您使用的是Spring,而且还有一些特别针对Spring的附加功能

    附言: 1.消费:

    我如何使用这段代码发送消息?我不需要吗 要将其放入队列中?java.io.OutputStream os= response.getOutputStream();java.io.ObjectOutputStream oos=new ObjectOutputStream(os);oos.writeObject(msg); 对于接收这样的smth: `

  • 我相信只有当接收者没有正确地接收到消息时,死区通道才会出现 接收并处理了它,但在处理它时失败 一些例外。我想让发件人知道有一个 异常,消息未成功处理。我可以这样做 使用响应队列,但我不想这样做,接收方可以吗 从同一队列中的发件人接收消息?如何接收
  • 死信通道也是一种用于消息处理的错误处理。如果消息处理失败,则在限制结束后,它会被传输到那里。它实际上不仅用于传输问题,而且也用于处理问题。如果消息处理异常失败,则消息将保留在队列中,不会被默认设置。那么我们应该如何处理此消息?例如,如果它由于数据库错误或类似的smth而失败?我们应该启动错误处理过程,通知保证系统和利益相关者,收集所有必要的信息并保存此消息。由于正是为此创建了此类队列,因此更容易处理。并且en客户支持团队将调查错误队列,以进一步分析发生的情况。此外,我们还提供了用于通知和收集此类错误统计信息的监控工具。了解发生的情况后,消息将从队列中删除并存档

    处理消息后,消费者负责删除 消息。例如,如果消费者没有删除消息 因为它在处理消息时崩溃了,消息 在消息的可见性超时过期后再次可见。 每次发生这种情况时,消息的接收计数都会增加
        <bean id="connectionFactory" class="org.springframework.
          jndi.JndiObjectFactoryBean">
            <property name="jndiTemplate" ref="baseJNDITemplate"/>
            <property name="jndiName"  
    
            value="weblogic.jms.ConnectionFactory"/>
        </bean>
    
        <bean id="queue"  class="org.springframework.
         jndi.JndiObjectFactoryBean">
            <property name="jndiTemplate" ref="baseJNDITemplate"/>
            <property name="jndiName" value="#{properties.queueName}"/>
        </bean>
    
        <bean id="messageListenerContainer"              
        class="org.springframework.jms.listener.
          DefaultMessageListenerContainer">
            <property name="connectionFactory" ref="connectionFactory"/>
            <property name="destination" ref="queue"/>
            <property name="messageListener" ref="messageListener"/>
            <property name="sessionTransacted" value="true"/>
        </bean>
    
        <bean id="messageListener" class="com.example.ABCListener"/>
    
    <bean id="jmsQueueTemplate" 
      class="org.springframework.
         jms.core.JmsTemplate">
    <property name="connectionFactory">
        <ref bean="jmsConnectionFactory"/>
    </property>
    <property name="destinationResolver">
        <ref bean="jmsDestResolver"/>
    </property>
    
    ...
    </bean>
    
    <bean id="jmsDestResolver"
          class=" org.springframework.jms.support.destination.
          JndiDestinationResolver"/>
    
    <bean id="jmsConnectionFactory"
          class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:comp/env/jms/myCF"/>
        <property name="lookupOnStartup" value="false"/>
        <property name="cache" value="true"/>
        <property name="proxyInterface" value="amq con fact here"/>
    </bean>
    
    @Autowired
    ConnectionFactory connectionFactory;
    
    @Test(enabled = false)
    public void testJmsSend(final String msg) throws Exception {
        JmsTemplate template = new JmsTemplate(connectionFactory);
        template.send("test_queue", new MessageCreator() {
            @Override
            public Message createMessage(Session session) 
              throws JMSException {
                return session.createTextMessage(msg);
            }
        });
    }
    
    public class AsynchronousJmsSenderServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String msg = null;
    
        try (java.io.OutputStream os = response.getOutputStream()) {
            try(java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream(os)) {
                oos.writeObject(msg);
            }
        }
    
        sendJmsMessage(msg);
    }
    
    private void sendJmsMessage(final String msg) {
        ConnectionFactory connectionFactory = null; //here get it in some way from spring
        JmsTemplate template = new JmsTemplate(connectionFactory);
        template.send("your_queue_name", new MessageCreator() {
            @Override
            public Message createMessage(Session session)
                    throws JMSException {
                return session.createTextMessage(msg);
            }
        });
    }
    }
    
    public class SynchronousJmsSenderServlet extends HttpServlet {
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String msg = null;
        try (java.io.OutputStream os = response.getOutputStream()) {
            try(java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream(os)) {
                oos.writeObject(msg);
            }
        }
        sendJmsMessage(msg);
    }
    
    private void sendJmsMessage(final String msg) {
        ConnectionFactory connectionFactory = null; //here get it in some way from spring
        JmsTemplate template = new JmsTemplate(connectionFactory);
    
        Message reply = template.sendAndReceive("your_queue_name", new MessageCreator() {
            @Override
            public Message createMessage(Session session)
                    throws JMSException {
                return session.createTextMessage(msg);
            }
        });
    
        if(reply instanceof TextMessage) {
            try {
                String status = ((TextMessage) reply).getText();
                //do error handling if status is error
            } catch (JMSException ex) {
                throw new RuntimeException("Unable to get status message", ex);
            }
        } else {
            throw new RuntimeException("Only text messages are supported");
        }
    }
    }
    
    
    public class SynchronousJmsMessageListener implements SessionAwareMessageListener {
    
    @Override
    public void onMessage(Message request, Session session) throws JMSException {
        try {
            //do some processing
            sendReply(request, session, "OK");
        } catch (Exception ex) {
            sendReply(request, session, "Error: " + ex.toString());
        }
    }
    
    private void sendReply(Message request, Session session, String status) {
        try {
            TextMessage reply = null; //for example you can use ActiveMQTextMessage here
            reply.setJMSCorrelationID(request.getJMSCorrelationID());
            reply.setText(status);
    
            MessageProducer producer = session.createProducer(reply.getJMSReplyTo());
            producer.send(reply);
        } catch (JMSException exception) {
            throw new RuntimeException("Unable to send reply", exception);
        }
    }
    }