Java 如何仅从JMS队列中手动获取特定类型的消息,并保留所有其他消息?

Java 如何仅从JMS队列中手动获取特定类型的消息,并保留所有其他消息?,java,jakarta-ee,jms,Java,Jakarta Ee,Jms,我有一个队列,其中包含消息,它们都是围绕不同的消息类型包装的ObjectMessage,这些消息类型都扩展了MyCustomMessage,例如MyClientMessage,MyInternalMessage。我想做以下工作: 客户端登录到系统 手动查找message.getObject()将返回MyClientMessage 如果消息属于该类型,但clientId不是登录用户的,请将其放回消息队列 我该怎么做 Connection connection = null; Session ses

我有一个队列,其中包含消息,它们都是围绕不同的消息类型包装的
ObjectMessage
,这些消息类型都扩展了
MyCustomMessage
,例如
MyClientMessage
MyInternalMessage
。我想做以下工作:

  • 客户端登录到系统
  • 手动查找
    message.getObject()
    将返回
    MyClientMessage
  • 如果消息属于该类型,但
    clientId
    不是登录用户的,请将其放回消息队列
  • 我该怎么做

    Connection connection = null;
    Session session = null;
    try {
        connection = factory.createConnection();
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    
        //Get a consumer
        MessageConsumer consumer = session.createConsumer( myQueue );
    
        //Start the connection
        connection.start();
    
        //Try to read a message
        Message response = consumer.receive(QUALITY_OF_SERVICE_THRESHOLD_MS);
    
        //Is anything like this possible?
        ObjectMessage<T> objMessage = ( ObjectMessage<T> ) response;
    
        //How check object is right type? Only this?
        if ( !objMessage.isBodyAssignableTo( typeClass ) )
        {
            //put back in queue? Or does it stay there until acknowledge?
    
        }
    
        //It's the right type
        else
        {
            objMessage.acknowledge();
        }
    
    
    } finally {
        if (connection != null) {
            connection.close();
        }
    }
    
    Connection=null;
    会话=空;
    试一试{
    connection=factory.createConnection();
    会话=connection.createSession(false,session.AUTO_-ACKNOWLEDGE);
    //获得消费者
    MessageConsumer=session.createConsumer(myQueue);
    //启动连接
    connection.start();
    //试着读一条消息
    消息响应=消费者接收(服务质量阈值);
    //这样做可能吗?
    ObjectMessage objMessage=(ObjectMessage)响应;
    //如何检查对象是否为正确类型?仅此?
    如果(!objMessage.isBodyAssignableTo(typeClass))
    {
    //把它放回队列?还是一直排到确认为止?
    }
    //这是正确的类型
    其他的
    {
    objMessage.acknowledge();
    }
    }最后{
    if(连接!=null){
    connection.close();
    }
    }
    
    您可以使用“JMS消息选择器”(最好是阅读JMS规范第3.8节,或者您也可以阅读一些描述,或者阅读一些理论)。基本上,JMS消息选择器允许JMS提供者只过滤和发送JMS消费者感兴趣的消息,而不发送JMS提供者接收的所有消息

    所以,它是这样的:

    • 消息生成器将生成具有某些特定属性的消息,以启用消息选择
    • 消息使用者将创建指定消息选择条件的使用者
    • 在将消息传递给该使用者之前,JMS提供程序将检查该使用者指定的消息选择标准是否满足,如果不满足,则不会将该特定消息传递给该特定使用者
    在producer端,您可以指定如下所示的string属性,这只是一个示例,您可以添加对您有意义的string属性

            Message hellowWorldText = session.createTextMessage("Hello World! " + new Date());
            hellowWorldText.setStringProperty("StockSector", "Technology");
    
    在使用者端,创建使用者时,可以指定消息选择条件:

            String selector = new String("(StockSector = 'Technology')");
            MessageConsumer consumer = session.createConsumer(queue, selector);
    
    请注意,您可以指定多个邮件选择属性/条件,因此根据您的需要,您可以添加任意多个条件,您可以将它们分组到单个条件中,也可以添加单独的条件

    下面是完整的工作代码示例,您只需要确保生产者和消费者的选择器匹配,因此在生产者中,您不能使用诸如当前日期/时间戳之类的内容作为消息选择属性,因为在消费者端,您不能指定相同的内容

    JmsProducerQueueClient:

    import java.util.Date;
    import java.util.Hashtable;
    
    import javax.jms.Connection;
    import javax.jms.ConnectionFactory;
    import javax.jms.JMSException;
    import javax.jms.Message;
    import javax.jms.MessageProducer;
    import javax.jms.Queue;
    import javax.jms.QueueSession;
    import javax.jms.Session;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    
    public class JmsProducerQueueClient {
        public static void main(String[] args) throws NamingException, JMSException {
            Connection connection = null;
            try {
                Context context = getInitialContext();
                ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup("ConnectionFactory2");
                connection = connectionFactory.createConnection();
                Session session = connection.createSession(false, QueueSession.AUTO_ACKNOWLEDGE);
                Queue queue = (Queue) context.lookup("Queue0");
                connection.start();
                MessageProducer producer = session.createProducer(queue);
                Message hellowWorldText = session.createTextMessage("Hello World! " + new Date());
                hellowWorldText.setStringProperty("StockSector", "Finance");
                producer.send(hellowWorldText);
            } finally {
                if (connection != null) {
                    connection.close();
                }
            }
    
        }
    
        @SuppressWarnings({ "rawtypes", "unchecked" })
        public static Context getInitialContext() throws NamingException {
            Hashtable env = new Hashtable();
            env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
            env.put(Context.PROVIDER_URL, "t3://localhost:8208");
            Context context = new InitialContext(env);
            return context;
        }
    }
    
    import java.util.Hashtable;
    
    import javax.jms.Connection;
    import javax.jms.ConnectionFactory;
    import javax.jms.JMSException;
    import javax.jms.MessageConsumer;
    import javax.jms.Queue;
    import javax.jms.QueueSession;
    import javax.jms.Session;
    import javax.jms.TextMessage;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    
    public class JmsConsumerQueueClient {
        public static void main(String[] args) throws NamingException, JMSException {
            Connection connection = null;
            try {
                Context context = getInitialContext();
                ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup("ConnectionFactory1");
                connection = connectionFactory.createConnection();
                Session session = connection.createSession(false, QueueSession.AUTO_ACKNOWLEDGE);
                Queue queue = (Queue) context.lookup("Queue0");
                String selector = new String("(StockSector = 'Technology')");
                MessageConsumer consumer = session.createConsumer(queue, selector);
                connection.start();
                TextMessage hellowWorldText = (TextMessage) consumer.receive();
    
                System.out.println("> " + hellowWorldText + " | " + hellowWorldText.getText());
    
            } finally {
                if (connection != null) {
                    connection.close();
                }
            }
    
        }
    
        @SuppressWarnings({ "unchecked", "rawtypes" })
        public static Context getInitialContext() throws NamingException {
            Hashtable env = new Hashtable();
            env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
            env.put(Context.PROVIDER_URL, "t3://localhost:7001");
            Context context = new InitialContext(env);
            return context;
        }
    }
    
    JmsConsumerQueueClient:

    import java.util.Date;
    import java.util.Hashtable;
    
    import javax.jms.Connection;
    import javax.jms.ConnectionFactory;
    import javax.jms.JMSException;
    import javax.jms.Message;
    import javax.jms.MessageProducer;
    import javax.jms.Queue;
    import javax.jms.QueueSession;
    import javax.jms.Session;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    
    public class JmsProducerQueueClient {
        public static void main(String[] args) throws NamingException, JMSException {
            Connection connection = null;
            try {
                Context context = getInitialContext();
                ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup("ConnectionFactory2");
                connection = connectionFactory.createConnection();
                Session session = connection.createSession(false, QueueSession.AUTO_ACKNOWLEDGE);
                Queue queue = (Queue) context.lookup("Queue0");
                connection.start();
                MessageProducer producer = session.createProducer(queue);
                Message hellowWorldText = session.createTextMessage("Hello World! " + new Date());
                hellowWorldText.setStringProperty("StockSector", "Finance");
                producer.send(hellowWorldText);
            } finally {
                if (connection != null) {
                    connection.close();
                }
            }
    
        }
    
        @SuppressWarnings({ "rawtypes", "unchecked" })
        public static Context getInitialContext() throws NamingException {
            Hashtable env = new Hashtable();
            env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
            env.put(Context.PROVIDER_URL, "t3://localhost:8208");
            Context context = new InitialContext(env);
            return context;
        }
    }
    
    import java.util.Hashtable;
    
    import javax.jms.Connection;
    import javax.jms.ConnectionFactory;
    import javax.jms.JMSException;
    import javax.jms.MessageConsumer;
    import javax.jms.Queue;
    import javax.jms.QueueSession;
    import javax.jms.Session;
    import javax.jms.TextMessage;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    
    public class JmsConsumerQueueClient {
        public static void main(String[] args) throws NamingException, JMSException {
            Connection connection = null;
            try {
                Context context = getInitialContext();
                ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup("ConnectionFactory1");
                connection = connectionFactory.createConnection();
                Session session = connection.createSession(false, QueueSession.AUTO_ACKNOWLEDGE);
                Queue queue = (Queue) context.lookup("Queue0");
                String selector = new String("(StockSector = 'Technology')");
                MessageConsumer consumer = session.createConsumer(queue, selector);
                connection.start();
                TextMessage hellowWorldText = (TextMessage) consumer.receive();
    
                System.out.println("> " + hellowWorldText + " | " + hellowWorldText.getText());
    
            } finally {
                if (connection != null) {
                    connection.close();
                }
            }
    
        }
    
        @SuppressWarnings({ "unchecked", "rawtypes" })
        public static Context getInitialContext() throws NamingException {
            Hashtable env = new Hashtable();
            env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
            env.put(Context.PROVIDER_URL, "t3://localhost:7001");
            Context context = new InitialContext(env);
            return context;
        }
    }
    
    您可以使用“JMS消息选择器”(最好是阅读JMS规范第3.8节,或者您也可以阅读一些描述,或者阅读理论)。基本上,JMS消息选择器允许JMS提供者只过滤和发送JMS消费者感兴趣的消息,而不发送JMS提供者接收的所有消息

    所以,它是这样的:

    • 消息生成器将生成具有某些特定属性的消息,以启用消息选择
    • 消息使用者将创建指定消息选择条件的使用者
    • 在将消息传递给该使用者之前,JMS提供程序将检查该使用者指定的消息选择标准是否满足,如果不满足,则不会将该特定消息传递给该特定使用者
    在producer端,您可以指定如下所示的string属性,这只是一个示例,您可以添加对您有意义的string属性

            Message hellowWorldText = session.createTextMessage("Hello World! " + new Date());
            hellowWorldText.setStringProperty("StockSector", "Technology");
    
    在使用者端,创建使用者时,可以指定消息选择条件:

            String selector = new String("(StockSector = 'Technology')");
            MessageConsumer consumer = session.createConsumer(queue, selector);
    
    请注意,您可以指定多个邮件选择属性/条件,因此根据您的需要,您可以添加任意多个条件,您可以将它们分组到单个条件中,也可以添加单独的条件

    下面是完整的工作代码示例,您只需要确保生产者和消费者的选择器匹配,因此在生产者中,您不能使用诸如当前日期/时间戳之类的内容作为消息选择属性,因为在消费者端,您不能指定相同的内容

    JmsProducerQueueClient:

    import java.util.Date;
    import java.util.Hashtable;
    
    import javax.jms.Connection;
    import javax.jms.ConnectionFactory;
    import javax.jms.JMSException;
    import javax.jms.Message;
    import javax.jms.MessageProducer;
    import javax.jms.Queue;
    import javax.jms.QueueSession;
    import javax.jms.Session;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    
    public class JmsProducerQueueClient {
        public static void main(String[] args) throws NamingException, JMSException {
            Connection connection = null;
            try {
                Context context = getInitialContext();
                ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup("ConnectionFactory2");
                connection = connectionFactory.createConnection();
                Session session = connection.createSession(false, QueueSession.AUTO_ACKNOWLEDGE);
                Queue queue = (Queue) context.lookup("Queue0");
                connection.start();
                MessageProducer producer = session.createProducer(queue);
                Message hellowWorldText = session.createTextMessage("Hello World! " + new Date());
                hellowWorldText.setStringProperty("StockSector", "Finance");
                producer.send(hellowWorldText);
            } finally {
                if (connection != null) {
                    connection.close();
                }
            }
    
        }
    
        @SuppressWarnings({ "rawtypes", "unchecked" })
        public static Context getInitialContext() throws NamingException {
            Hashtable env = new Hashtable();
            env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
            env.put(Context.PROVIDER_URL, "t3://localhost:8208");
            Context context = new InitialContext(env);
            return context;
        }
    }
    
    import java.util.Hashtable;
    
    import javax.jms.Connection;
    import javax.jms.ConnectionFactory;
    import javax.jms.JMSException;
    import javax.jms.MessageConsumer;
    import javax.jms.Queue;
    import javax.jms.QueueSession;
    import javax.jms.Session;
    import javax.jms.TextMessage;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    
    public class JmsConsumerQueueClient {
        public static void main(String[] args) throws NamingException, JMSException {
            Connection connection = null;
            try {
                Context context = getInitialContext();
                ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup("ConnectionFactory1");
                connection = connectionFactory.createConnection();
                Session session = connection.createSession(false, QueueSession.AUTO_ACKNOWLEDGE);
                Queue queue = (Queue) context.lookup("Queue0");
                String selector = new String("(StockSector = 'Technology')");
                MessageConsumer consumer = session.createConsumer(queue, selector);
                connection.start();
                TextMessage hellowWorldText = (TextMessage) consumer.receive();
    
                System.out.println("> " + hellowWorldText + " | " + hellowWorldText.getText());
    
            } finally {
                if (connection != null) {
                    connection.close();
                }
            }
    
        }
    
        @SuppressWarnings({ "unchecked", "rawtypes" })
        public static Context getInitialContext() throws NamingException {
            Hashtable env = new Hashtable();
            env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
            env.put(Context.PROVIDER_URL, "t3://localhost:7001");
            Context context = new InitialContext(env);
            return context;
        }
    }
    
    JmsConsumerQueueClient:

    import java.util.Date;
    import java.util.Hashtable;
    
    import javax.jms.Connection;
    import javax.jms.ConnectionFactory;
    import javax.jms.JMSException;
    import javax.jms.Message;
    import javax.jms.MessageProducer;
    import javax.jms.Queue;
    import javax.jms.QueueSession;
    import javax.jms.Session;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    
    public class JmsProducerQueueClient {
        public static void main(String[] args) throws NamingException, JMSException {
            Connection connection = null;
            try {
                Context context = getInitialContext();
                ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup("ConnectionFactory2");
                connection = connectionFactory.createConnection();
                Session session = connection.createSession(false, QueueSession.AUTO_ACKNOWLEDGE);
                Queue queue = (Queue) context.lookup("Queue0");
                connection.start();
                MessageProducer producer = session.createProducer(queue);
                Message hellowWorldText = session.createTextMessage("Hello World! " + new Date());
                hellowWorldText.setStringProperty("StockSector", "Finance");
                producer.send(hellowWorldText);
            } finally {
                if (connection != null) {
                    connection.close();
                }
            }
    
        }
    
        @SuppressWarnings({ "rawtypes", "unchecked" })
        public static Context getInitialContext() throws NamingException {
            Hashtable env = new Hashtable();
            env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
            env.put(Context.PROVIDER_URL, "t3://localhost:8208");
            Context context = new InitialContext(env);
            return context;
        }
    }
    
    import java.util.Hashtable;
    
    import javax.jms.Connection;
    import javax.jms.ConnectionFactory;
    import javax.jms.JMSException;
    import javax.jms.MessageConsumer;
    import javax.jms.Queue;
    import javax.jms.QueueSession;
    import javax.jms.Session;
    import javax.jms.TextMessage;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    
    public class JmsConsumerQueueClient {
        public static void main(String[] args) throws NamingException, JMSException {
            Connection connection = null;
            try {
                Context context = getInitialContext();
                ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup("ConnectionFactory1");
                connection = connectionFactory.createConnection();
                Session session = connection.createSession(false, QueueSession.AUTO_ACKNOWLEDGE);
                Queue queue = (Queue) context.lookup("Queue0");
                String selector = new String("(StockSector = 'Technology')");
                MessageConsumer consumer = session.createConsumer(queue, selector);
                connection.start();
                TextMessage hellowWorldText = (TextMessage) consumer.receive();
    
                System.out.println("> " + hellowWorldText + " | " + hellowWorldText.getText());
    
            } finally {
                if (connection != null) {
                    connection.close();
                }
            }
    
        }
    
        @SuppressWarnings({ "unchecked", "rawtypes" })
        public static Context getInitialContext() throws NamingException {
            Hashtable env = new Hashtable();
            env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
            env.put(Context.PROVIDER_URL, "t3://localhost:7001");
            Context context = new InitialContext(env);
            return context;
        }
    }
    

    谢谢你,有一部分你没有提到:在某些情况下,我如何让我的消费者把它放回队列?(例如,某些客户端尚未准备好与创建
    MessageConsumer
    )的类进行通信@DonRhummy JMS提供程序将过滤掉消息并仅向消费者传递相关消息,因此JMS消费者没有任何责任进行过滤并将其放回,但是,如果您想这样做,那么您可以始终确认该消息(您刚刚使用的消息),从该消息创建一个新消息,然后将其放回同一队列,或者您可以使用其他队列。根据您的需求,JMS临时队列和JMSReplyTo标头可能对您有用。谢谢,我如何接收队列中的所有消息?我只看到了一种接收一条消息的方法。这不起作用。当我使用选择器创建消费者时(以及使用该字符串属性的原始消息),我没有收到任何消息。@DonRhummy我已使用完整的工作代码更新了我的答案,如果您