Springboot中配置activeMQ持久化

一、activeMQ數據庫持久化配置

ActiveMQ持久化的三種方式,我們採用數據庫的方式來進行持久化。

(1) Memory 消息存儲-基於內存的消息存儲。
(2) 基於日誌消息存儲方式,KahaDB是ActiveMQ的默認日誌存儲方式,它提供了容量的提升和恢復
能力。
(3) 基於JDBC的消息存儲方式-數據存儲於數據庫(例如:MySQL)中。

首先我們先來配置activeMQ

在conf文件夾裏的activeMQ.xml中增加一個jdbc的bean

<bean id="activemq-db" class="org.apache.commons.dbcp.BasicDataSource">
                      <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
                      <property name="url" value="jdbc:mysql://127.0.0.1:3306/test"/>
                      <property name="username" value="root"/>
                      <property name="password" value="root"/>
                      <property name="maxActive" value="200"/>
                      <property name="poolPreparedStatements" value="true"/>
                    </bean>

 然後還是同一個文件,找到<persistenceAdapter>標籤修改:註釋掉原來的kahaDB方式持久化。

 <persistenceAdapter>
       <!--     <kahaDB directory="${activemq.base}/data/kahadb"/>  -->
<!--createTablesOnStartup    啓動是否創建表  第一次爲true 後續爲false-->
<jdbcPersistenceAdapter dataSource="#activemq-db" createTablesOnStartup="true" />
        </persistenceAdapter>

 接着需要將一些jar包放在lib目錄裏。因爲我們用的是連接池和mysql,所以要導入四個jar包

 配置好的MQ下載地址:https://download.csdn.net/download/qq_39404258/12561459

如果啓動失敗,報下面這樣的錯,說明你的mysql和mysql連接的jar包不匹配:

Uncategorized exception occurred during JMS processing; nested exception is javax.jms.JMSException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'OPTION SQL_SELECT_LIMIT=DEFAULT' at line 1

我用的mysql是5.6,用的mysql-connector是5.0.8,出現了這樣的錯,將mysql-connector改成了5.1.21就正常運行了。版本以自己的實際爲主。

二、ActiveMQ的兩種模型

點對點模型 queue

每個消息只有一個消費者( Consumer)(即一旦被消費,消息就不再在消息隊列中);
發送者和接收者之間在時間上沒有依賴性,也就是說當發送者發送了消息之後,不管接收者有沒有
正在運行,它不會影響到消息被髮送到隊列;
接收者在成功接收消息之後需向隊列應答成功。

發佈/訂閱模型 topic

每個消息可以有多個消費者;
發佈者和訂閱者之間有時間上的依賴性(先訂閱主題,再來發送消息)。
訂閱者必須保持運行的狀態,才能接受發佈者發佈的消息

 

使用jms原生消息進行示例:

生產者:

public class ProducerJMS {
    public static String TCP_PATH="tcp://127.0.0.1:61616";
    public static void main(String[] args) {
        try {
            //1.創建連接工廠
            ConnectionFactory factory = new ActiveMQConnectionFactory();
            //2.創建連接
            Connection connection=factory.createConnection();
            //3.打開連接
            connection.start();
            //4.創建session param1=事務是否開啓 param2=消息確認機制  如果開啓事務,第二個參數無用,且需要一個提交事務的操作
            Session session=connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
            //5.創建消息隊列
            Topic topic =session.createTopic("q2");
            Queue queue=session.createQueue("q1");
            MessageProducer producer1=session.createProducer(topic);
            //6.創建生產者
            MessageProducer producer=session.createProducer(queue);

            //7.創建消息
            TextMessage textMessage=session.createTextMessage("new");
            TextMessage textMessage1=session.createTextMessage("new1");
            TextMessage textMessage2=session.createTextMessage("new2");
            TextMessage top1=session.createTextMessage("top");
            TextMessage top2=session.createTextMessage("top1");
            TextMessage top3=session.createTextMessage("top2");
            //8.發送消息到消息隊列
            producer.send(textMessage);
            producer.send(textMessage1);
            producer.send(textMessage2);
            producer1.send(top2);
            producer1.send(top3);
            producer1.send(top1);
            //9.關閉連接
            session.close();
            connection.close();
        }catch (Exception e){
            e.printStackTrace();
        }


    }
}

消費者:

public class ConsumerJMS {
    public static String URL_PATH="tcp://127.0.0.1:61616";
    public static void main(String[] args) {
        try{
            //1.創建連接工廠
            ConnectionFactory factory = new ActiveMQConnectionFactory(URL_PATH);
            //2.創建連接
            Connection connection = factory.createConnection();
            //3.打開連接
            connection.start();
            //4.創建會話
            Session session=connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
            //5.創建目標地址(通道)
            Queue queue =session.createQueue("q1");
            Topic topic = session .createTopic("q2");
            //6.創建消費者
            MessageConsumer consumer1=session.createConsumer(topic);
            MessageConsumer consumer=session.createConsumer(queue);
            consumer1.setMessageListener(new MessageListener() {
                @Override
                public void onMessage(Message message) {
                    if (message instanceof TextMessage){
                        TextMessage textMessage = (TextMessage) message;
                        try {
                            System.out.println("接收的消息:"+textMessage.getText());
                        } catch (JMSException e) {
                            e.printStackTrace();
                        }
                    }else {
                        System.out.println("類型錯誤!");
                    }
                }
            });
            //7.接收消息,因爲在一直監聽,當有新消息來時,獲取,所以連接不能關
            consumer.setMessageListener(new MessageListener() {
                @Override
                public void onMessage(Message message) {
                    if (message instanceof TextMessage){
                        TextMessage textMessage = (TextMessage) message;
                        try {
                            System.out.println("接收的消息:"+textMessage.getText());
                        } catch (JMSException e) {
                            e.printStackTrace();
                        }
                    }else {
                        System.out.println("類型錯誤!");
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }

    }



}

 啓動兩個消費者,然後啓動生產者,結果:

通過結果發現,queue的消息隨機分配給了兩個消費者,但topic的消息同時發給了他們兩個。
接着先啓動生產者,再啓動消費者,發現只收到了queue裏的消息。

三、在springboot中簡單使用

 

yml配置:

 

 

server:
  port: 9081
spring:
  activemq:
    broker-url: tcp://127.0.0.1:61616
    user: admin
    password: admin
    packages:
      trust-all: true  #信任包
  jms:
    pub-sub-domain: false #false點對點 true訂閱
    template:
      delivery-mode: persistent #持久化
activemq:
  name: spring_queue

maven依賴:

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>

五種消息的使用實例:

生產者:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes= ProducerApplication.class)
public class Producer {
    @Value("${activemq.name}")
    private String messageName;
    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;
    @Autowired
    private JmsTemplate jmsTemplate;

    @Test
    public void ptpSend() {
        jmsMessagingTemplate.convertAndSend("spring_queue", "new message");
    }

    @Test
    public void ptpSendTextMessage() {
        jmsTemplate.send(messageName, new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                return session.createTextMessage("testMessage");
            }
        });
    }
    @Test
    public void ptpSendMapMessage() {
        jmsTemplate.send(messageName, new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                MapMessage mapMessage =session.createMapMessage();
                mapMessage.setString("name","zz");
                mapMessage.setInt("age",1);
                return mapMessage;
            }
        });
    }
    @Test
    public void ptpSendUserMessage() {
        jmsTemplate.send(messageName, new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                User user= new User("zhangsan",11);
                return session.createObjectMessage(user);
            }
        });
    }
    @Test
    public void ptpSendByteMessage() {
        jmsTemplate.send(messageName, new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                File file =new File("D:\\img\\30.png");
               BytesMessage bytesMessage = session.createBytesMessage();
                try {
                    FileInputStream in = new FileInputStream(file);
                    byte[] bytes = new byte[(int)file.length()];
                    //將Stream裏的內容輸入到bytes裏
                    in.read(bytes);
                    bytesMessage.writeBytes(bytes);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return bytesMessage;
            }
        });
    }
    @Test
    public void ptpSendStreamMessage() {
        jmsTemplate.send(messageName, new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
              StreamMessage streamMessage =  session.createStreamMessage();
              streamMessage.writeDouble(2.2);
              streamMessage.writeString("Stream");
                return streamMessage;
            }
        });
    }
}

消費者:

@Component
public class Consumer {

    @JmsListener(destination = "${activemq.name}")
    public void reveiced(Message message){
        if (message instanceof TextMessage){
          TextMessage textMessage=(TextMessage) message;
            try {
                System.out.println("接收消息:"+textMessage.getText());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else if (message instanceof MapMessage){
            MapMessage mapMessage=(MapMessage) message;
            try {
                System.out.println("接收Map消息:"+mapMessage.getString("name")+","+mapMessage.getString("age"));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        else if (message instanceof ObjectMessage){
            ObjectMessage objectMessage=(ObjectMessage) message;
            try {
                User user = (User) objectMessage.getObject();
                System.out.println("接收Object消息:"+user.getName()+","+user.getAge());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        else if (message instanceof BytesMessage){   
            BytesMessage bytesMessage=(BytesMessage) message;
            try {
                FileOutputStream fileOutputStream = new FileOutputStream("D:\\img1\\1.png");
                byte[] bytes = new byte[(int)bytesMessage.getBodyLength()];
                bytesMessage.readBytes(bytes);
                fileOutputStream.write(bytes);
                fileOutputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        else if (message instanceof StreamMessage){
            StreamMessage streamMessage=(StreamMessage) message;
            try {
                System.out.println("接收Stream消息:"+streamMessage.readDouble());
                System.out.println("接收Stream消息:"+streamMessage.readString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

 

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