为了账号安全,请及时绑定邮箱和手机立即绑定

spring-消息

标签:
Java

1、异步消息

  当一个消息发送时候,消息会被交给消息代理,消息代理可以确保消息被发送到指定的目的地,同时解放发送者,使其能够继续进行其它业务。消息代理通常有ActiveMQ、RabbitMQ...,目的地通常有队列和主题,队列采用点对点的模型,主题采用发布订阅模型

  • 点对点模型:消息队 列可以有多个接受者,但每条消息只能被一个接收者取走

https://img1.sycdn.imooc.com//5b8c137e0001586a06450116.jpg

 

  • 发布订阅模型:消息队列可以有多个订阅者,每条消息可以发送给多个主题订阅者

https://img1.sycdn.imooc.com//5b8c138b0001032206450434.jpg

 

 2、JMS发送/接收消息

1)activemq配置,使用ActiveMQ,并使用了JMSTemplate。

  JMS模板为开发者提供了与消息代理进行交互发送和接收消息的标准API,几乎每个消息代理都支持JMS。Jms模板和spring Date提供的jdbc模板一样可以消除样板代码,让开发更集中在业务处理上。

复制代码

   <!-- ActiveMQ连接工厂 -->
    <bean id="activeMQConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://localhost:61616"></property>
    </bean>
    <!-- 消息队列 -->
    <bean id="queue" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg value="userqueue"></constructor-arg>
    </bean>
    <!-- 消息主题 -->
    <bean id="topic" class="org.apache.activemq.command.ActiveMQTopic">
        <constructor-arg value="usertopic"></constructor-arg>
    </bean>
    <!-- 定义模板 -->
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="activeMQConnectionFactory"></property>
  </bean>

复制代码

2)发送消息

复制代码

package com.cn.activemq;import com.cn.pojo.User;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.jms.core.JmsTemplate;import org.springframework.jms.core.MessageCreator;import org.springframework.stereotype.Component;import javax.jms.Destination;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.Session;

@Componentpublic class SendMessageMQUtil {

    @Autowired    private JmsTemplate jmsTemplate;

    @Autowired
    @Qualifier("queue")    private Destination queue;

    @Autowired
    @Qualifier("topic")    private Destination topic;    /**
     * 队列--发送消息
     * @param user     */
    public void sendUserQueue(final User user){

        jmsTemplate.send(queue, new MessageCreator() {            public Message createMessage(Session session) throws JMSException {                return session.createObjectMessage(user);
            }
        });
    }    /**
     * 主题--发送消息
     * @param user     */
    public void sendUserTopic(final User user){

        jmsTemplate.send(topic, new MessageCreator() {            public Message createMessage(Session session) throws JMSException {                return session.createObjectMessage(user);
            }
        });
    }
}

复制代码

3)接收消息

复制代码

package com.cn.activemq;import com.cn.pojo.User;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.jms.core.JmsTemplate;import org.springframework.stereotype.Component;import javax.jms.Destination;import javax.jms.JMSException;import javax.jms.ObjectMessage;

@Componentpublic class ReceiveMessageMQUtil {

    @Autowired    private JmsTemplate jmsTemplate;

    @Autowired
    @Qualifier("queue")    private Destination queue;

    @Autowired
    @Qualifier("topic")    private Destination topic;    /**
     * 队列--接受消息
     * @return
     */
    public User receiveUserQueue(){        try {
            ObjectMessage objectMessage=(ObjectMessage) jmsTemplate.receive(queue);            return (User)objectMessage.getObject();
        } catch (JMSException e) {
            e.printStackTrace();
        }        return null;
    }    /**
     * 主题--接受消息
     * @return
     */
    public User receiveUserTopic(){        try {
            ObjectMessage objectMessage=(ObjectMessage) jmsTemplate.receive(topic);            return (User)objectMessage.getObject();
        } catch (JMSException e) {
            e.printStackTrace();
        }        return null;
    }

}

复制代码

4)测试

分别新建测试类

复制代码

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring-activemq.xml", "classpath:spring-redis.xml","classpath:springMvc.xml"})//不可使用classpath:spring-*.xml,否则配置文件不起作用public class SendMessageMQUtilTest {

    @Autowired    private SendMessageMQUtil sendMessageMQUtil;

    @Test    public void sendUserQueue() throws Exception {
        User user=new User("computer1", "111111");
        sendMessageMQUtil.sendUserQueue(user);
    }

    @Test    public void sendUserTopic() throws Exception {
        User user=new User("computer2", "222222");
        sendMessageMQUtil.sendUserTopic(user);
    }
}

复制代码

复制代码

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring-activemq.xml", "classpath:spring-redis.xml","classpath:springMvc.xml"})public class ReceiveMessageMQUtilTest {

    @Autowired    private ReceiveMessageMQUtil receiveMessageMQUtil;

    @Test    public void receiveUserQueue() throws Exception {

        User user=receiveMessageMQUtil.receiveUserQueue();
        System.out.println("ActiveMQ接收到的数据:"+user);
    }

    @Test    public void receiveUserTopic() throws Exception {

        User user=receiveMessageMQUtil.receiveUserTopic();
        System.out.println("ActiveMQ接收到的数据:"+user);
    }

    @Test    public void receiveUserTopic2() throws Exception {

        User user=receiveMessageMQUtil.receiveUserTopic();
        System.out.println("ActiveMQ接收到的数据:"+user);
    }

}

复制代码

分别运行测试方法,结合activeMQ的控制台可以看出队列、主题以及各自的消费者等情况

显示队列:

https://img1.sycdn.imooc.com//5b8c13960001336807580327.jpg

显示主题:

      https://img1.sycdn.imooc.com//5b8c139c0001d84a07480063.jpg

3、其它

1)设置默认的目的地

  上述在发送消息和接收消息时,每次调用发送/接收消息的方法都传入了一个目的地参数。然而,可以在JmsTemplate实例化的时候,指定默认的目的地,如下:

复制代码

    <!-- 定义队列 -->
    <bean id="queue" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg value="userqueue"></constructor-arg>
    </bean>
    <!-- 定义模板 -->
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="activeMQConnectionFactory"></property>
        <property name="defaultDestination" ref="queue"></property>//此处注入队列,也可以注入主题
    </bean>

复制代码

采用指定默认目的地的方式,则发送/接收消息调用的方法不用传递目的地了

复制代码

 /**
     * 队列--发送消息
     * @param user     */
    public void sendUserQueue(final User user){

        jmsTemplate.send(new MessageCreator() {            public Message createMessage(Session session) throws JMSException {                return session.createObjectMessage(user);
            }
        }); /**
     * 队列--接受消息
     * @return
     */
    public User receiveUserQueue(){        try {
            ObjectMessage objectMessage=(ObjectMessage) jmsTemplate.receive();            return (User)objectMessage.getObject();
        } catch (JMSException e) {
            e.printStackTrace();
        }        return null;
    }
   }

复制代码

2)发送消息对消息进行转换

  除了send(..)方法,JmsTemplate还提供了convertAndSend()方法,该方法不需要MessageCreator参数,而使用内置的消息转换器创建消息并发送。在JmsTemplate实例化时未指定消息转换器,在调用convertAndSend()方法则使用默认的SimpleMessageConverter消息转换器;receiveAndConvert()方法则在接收时候使用消息转换器

复制代码

/**
     * 队列--发送消息
     * @param user     */
    public void sendUserQueue(final User user){

        jmsTemplate.convertAndSend(user);
    }    /**
     * 队列--接受消息
     * @return
     */
    public User receiveUserQueue(){        return (User)jmsTemplate.receiveAndConvert();
    }

复制代码

在JmsTemplate实例化指定消息转换器,则会在使用convertAndSend()/receiveAndConvert()方法使用指定的消息转换器

复制代码

    <!-- 定义队列 -->
    <bean id="queue" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg value="userqueue"></constructor-arg>
    </bean>
    <!-- 消息转换器  -->
    <bean id="mappingJackson2MessageConverter" class="org.springframework.jms.support.converter.MappingJackson2MessageConverter"></bean>
    <!-- 定义模板 -->
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="activeMQConnectionFactory"></property>
        <property name="defaultDestination" ref="queue"></property>
        <property name="messageConverter" ref="mappingJackson2MessageConverter"></property>
    </bean>

复制代码

综合1)2),使用convertAndSend()/receiveAndConvert()发送和接收消息更加简单;在某些情况下,统一配置目的地也简化的使用

原文出处:https://www.cnblogs.com/shixiemayi/p/9574191.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消