springboot整合activeMQ -- Queue模式(篇二)

前言

上篇讲了activeMQ之Queue(队列)基础知识点,在此基础上加入websocket,消息的持久化、消费者手动签收机制、消息重发机制。
springboot整合activeMQ系列之Queue(一)

在系列一的基础上对消费者工程改造

pom文件增加了

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
        </dependency>

消费者目录

在这里插入图片描述

配置文件

配置文件有websocket的配置和activeMQ队列的持久化、签收、重发机制的相关设计

package com.example.bootcustomer.config;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.RedeliveryPolicy;
import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

import javax.jms.DeliveryMode;
import javax.jms.Queue;
import javax.jms.Session;

/**
 * @Desc 消费者和生产者的配置类差不多,生产者不用配置websocket去掉就好,其他都是一样的
 */
@Configuration
@EnableJms
public class BeanConfig {
    @Value("${myQueue}")
    private String myQueue;

    /**
     * websocket配置Bean
     *
     * @return
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

    /**
     * 定义存放消息的队列
     * @return
     */
    @Bean
    public Queue queue() {
        return new ActiveMQQueue(myQueue);
    }

    @Bean
    public RedeliveryPolicy redeliveryPolicy() {
        RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
        //是否在每次尝试重新发送失败后,增长这个等待时间
        redeliveryPolicy.setUseExponentialBackOff(true);
        //重发次数,默认为6次   这里设置为10次
        redeliveryPolicy.setMaximumRedeliveries(10);
        //重发时间间隔,默认为1秒
        redeliveryPolicy.setInitialRedeliveryDelay(1);
        //第一次失败后重新发送之前等待500毫秒,第二次失败再等待500 * 2毫秒,这里的2就是value
        redeliveryPolicy.setBackOffMultiplier(2);
        //是否避免消息碰撞
        redeliveryPolicy.setUseCollisionAvoidance(false);
        //设置重发最大拖延时间10s   只有UseExponentialBackOff(true)为true时才表示没有拖延时间
        redeliveryPolicy.setMaximumRedeliveryDelay(10000L);
        return redeliveryPolicy;
    }

    @Bean
    public ActiveMQConnectionFactory activeMQConnectionFactory(RedeliveryPolicy redeliveryPolicy) {
        ActiveMQConnectionFactory activeMQConnectionFactory =
                new ActiveMQConnectionFactory();
        activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);
        return activeMQConnectionFactory;
    }

    @Bean
    public JmsTemplate jmsTemplate(ActiveMQConnectionFactory activeMQConnectionFactory, Queue queue) {
        JmsTemplate jmsTemplate = new JmsTemplate();
        jmsTemplate.setDeliveryMode(DeliveryMode.PERSISTENT);//进行持久化配置  NON_PERSISTENT - 表示非持久化,PERSISTENT - 表示持久化
        jmsTemplate.setConnectionFactory(activeMQConnectionFactory);
        jmsTemplate.setDefaultDestination(queue); //此处可不设置默认,在发送消息时也可设置队列
        jmsTemplate.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);//客户端签收模式
        //  CLIENT_ACKNOWLEDGE -- 客户确认        DUPS_OK_ACKNOWLEDGE --  自动批量确认
        //  SESSION_TRANSACTED -- 事务提交并确认   AUTO_ACKNOWLEDGE -- 自动签收
        return jmsTemplate;
    }


    /**
     * 定义一个消息监听器连接工厂,这里定义的是点对点模式的监听器连接工厂
     *
     * @param activeMQConnectionFactory
     * @return
     */
    @Bean(name = "jmsQueueListener")
    public DefaultJmsListenerContainerFactory jmsQueueListenerContainerFactory(ActiveMQConnectionFactory activeMQConnectionFactory) {
        DefaultJmsListenerContainerFactory factory =
                new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(activeMQConnectionFactory);
        //设置连接数
        factory.setConcurrency("1-10");
        //重连间隔时间
        factory.setRecoveryInterval(10000L);
        factory.setSessionAcknowledgeMode(4);
        return factory;
    }
}

Queue_Customer类

package com.example.bootcustomer.customer;

import lombok.Data;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

import javax.jms.JMSException;
import javax.jms.TextMessage;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.Session;

/**
 * @Desc 消费者类
 */
@ServerEndpoint("/websocket")
@Component
@Data
public class Queue_Customer {
    /**
     * 每个客户端都会有相应的session,服务端可以发送相关消息
     */
    private Session session;

    /**
     * J.U.C包下线程安全的类,主要用来存放每个客户端对应的webSocket连接
     */
    private static CopyOnWriteArraySet<Queue_Customer> copyOnWriteArraySet = new CopyOnWriteArraySet<>();

    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        copyOnWriteArraySet.add(this);
    }

    @OnClose
    public void onClose() {
        copyOnWriteArraySet.remove(this);
    }

    @OnMessage
    public void onMessage(String message) {
    }

    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }


    @JmsListener(destination = "${myQueue}", containerFactory = "jmsQueueListener") //监听
    public void receive(TextMessage textMessage, javax.jms.Session session) throws JMSException {
        //遍历客户端
        for (Queue_Customer webSocket : copyOnWriteArraySet) {
            try {
                //服务器主动推送
                webSocket.session.getBasicRemote().sendText(textMessage.getText());
                textMessage.acknowledge();// 使用手动签收模式,需要手动的调用,如果不在catch中调用session.recover()消息只会在重启服务后重发
                System.out.println("websocket-1号消费者" + textMessage.getText());
            } catch (Exception e) {
                session.recover();// 此不可省略 重发信息使用
            }
        }
    }
}

启动类和系列一致springboot整合activeMQ系列之Queue(一),就不赘述了!

生产者工程

生产者工程需要把之前的配置文件改成和消费者一样,去掉websocket就可以,pom文件不用改。

Queue_Produce 类

package com.example.provider.produce;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.jms.Queue;
import java.util.UUID;

/**
 * @Desc 生产者
 */
@Component
public class Queue_Produce {
//    @Autowired
//    private JmsMessagingTemplate jmsMessagingTemplate; //系列一
    @Autowired
   private Queue queue;
    @Autowired
    private JmsTemplate jmsTemplate;

    /**
     * 间隔10秒钟定投
     */
    @Scheduled(fixedDelay = 10000)
    public void produceMsgScheduled() {
        jmsTemplate.convertAndSend(queue, "$$$$$$$:" + UUID.randomUUID().toString().substring(0, 7));
        System.out.println("produceMsgScheduled send ok");
    }
}

运行结果图:
生产者:
在这里插入图片描述
消费者:
在这里插入图片描述
activeMQ图:
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章