1. 程式人生 > >e3mall專案:商品增刪改查同步索引庫(ActiveMQ相關)

e3mall專案:商品增刪改查同步索引庫(ActiveMQ相關)

e3mall專案:商品增刪改查同步索引庫

準備工作:在e3-search-service和e3-manager-service的pom檔案中,新增ActiveMQ的依賴

<!--ActiveMQ訊息中介軟體-->
<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-all</artifactId>
</dependency>

一、在商品的增刪改查時,傳送需要同步索引庫的訊息。(訊息傳送端:e3-manager-service)

(1)在e3-manager-service中配置ActiveMQ。(在spring目錄中,新建配置檔案:applicationContext-activemq.xml)


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
	http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">


    <!-- 真正可以產生Connection的ConnectionFactory,由對應的 JMS服務廠商提供 -->
    <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="${activemq.url}" />  //這裡的activemq.url在resouce.properties中,你也可以直接寫在這裡
    </bean>
    <!-- Spring用於管理真正的ConnectionFactory的ConnectionFactory -->
    <bean id="connectionFactory"
          class="org.springframework.jms.connection.SingleConnectionFactory">
        <!-- 目標ConnectionFactory對應真實的可以產生JMS Connection的ConnectionFactory -->
        <property name="targetConnectionFactory" ref="targetConnectionFactory" />
    </bean>

    <!-- 配置生產者 -->
    <!-- Spring提供的JMS工具類,它可以進行訊息傳送、接收等 -->
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <!-- 這個connectionFactory對應的是我們定義的Spring提供的那個ConnectionFactory物件 -->
        <property name="connectionFactory" ref="connectionFactory" />
    </bean>
    <!--這個是佇列目的地,點對點的 -->
    <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg>
            <value>spring-queue</value>
        </constructor-arg>
    </bean>
    <!-- 商品資料更新訊息 -->
    <bean id="itemUpdate" class="org.apache.activemq.command.ActiveMQTopic">
        <constructor-arg value="itemUpdate" />
    </bean>
</beans>

(2)在完成商品資料修改之前,傳送訊息同步索引庫。(我這裡對傳送訊息進行了封裝,只需要在商品操作完成之前,呼叫即可)

封裝的方法如下:

    /**
     * 傳送訊息的方法
     * @auther: xushuai
     * @date: 2018/5/26 15:26
     */
    private void sendMessage(final long itemId, Destination destination) {
        jmsTemplate.send(destination, new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                //將商品ID傳送
                return session.createTextMessage(itemId + "");
            }
        });
    }

呼叫:



注意:需要注入JmsTemplate物件和Destination物件。(即spring容器中配置好的)

二、同步索引庫操作。(訊息接收端:e3-search-service)

(1)書寫訊息接收監聽器類(ItemUpdateMessageLinstener)
package cn.e3mall.search.message;

import cn.e3mall.search.service.SearchService;
import org.springframework.beans.factory.annotation.Autowired;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

/**
 * 商品資料更新訊息監聽器
 * Author: xushuai
 * Date: 2018/5/26
 * Time: 15:37
 * Description:
 */
public class ItemUpdateMessageLinstener implements MessageListener{

    @Autowired
    private SearchService searchService;

    @Override
    public void onMessage(Message message) {
        try {
            //等待一秒,防止訊息傳送端事務沒有提交,發生不必要的錯誤
            Thread.sleep(1000);
            //執行更新索引庫操作
            TextMessage textMessage = (TextMessage) message;
            Long itemId = Long.valueOf(textMessage.getText());
            searchService.syncIndex(itemId);
        } catch (JMSException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

(2)在e3-search-service中配置ActiveMQ。(在spring目錄中,新建applicationContext-activemq.xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
	http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">


    <!-- 真正可以產生Connection的ConnectionFactory,由對應的 JMS服務廠商提供 -->
    <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="${activemq.url}" />
    </bean>
    <!-- Spring用於管理真正的ConnectionFactory的ConnectionFactory -->
    <bean id="connectionFactory"
          class="org.springframework.jms.connection.SingleConnectionFactory">
        <!-- 目標ConnectionFactory對應真實的可以產生JMS Connection的ConnectionFactory -->
        <property name="targetConnectionFactory" ref="targetConnectionFactory" />
    </bean>

    <!-- 配置生產者 -->
    <!-- Spring提供的JMS工具類,它可以進行訊息傳送、接收等 -->
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <!-- 這個connectionFactory對應的是我們定義的Spring提供的那個ConnectionFactory物件 -->
        <property name="connectionFactory" ref="connectionFactory" />
    </bean>
    <!--這個是佇列目的地,點對點的 -->
    <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg>
            <value>spring-queue</value>
        </constructor-arg>
    </bean>
    <!-- 商品資料更新訊息 -->
    <bean id="itemUpdate" class="org.apache.activemq.command.ActiveMQTopic">
        <constructor-arg value="itemUpdate" />  //這裡的值,需要和訊息傳送方的值一致
    </bean>

    <!--配置訊息接收監聽器-->
    <bean id="itemUpdateMessageLinstener" class="cn.e3mall.search.message.ItemUpdateMessageLinstener"/>
    <!--商品資料更新訊息監聽器容器-->
    <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="connectionFactory" />
        <property name="destination" ref="itemUpdate" />
        <property name="messageListener" ref="itemUpdateMessageLinstener" />
    </bean>

</beans>

(3)在SearchService和SearchServiceImpl中,實現同步索引庫操作(抽象方法和實現)

    /**
     * 同步索引庫
     * @auther: xushuai
     * @date: 2018/5/26 15:40
     */
    void syncIndex(Long itemId);
    @Override
    public void syncIndex(Long itemId) {
        //根據ID查詢索引結果
        SearchResult searchResult = searchMapper.getItemById(itemId);
        if(searchResult != null){
            //說明商品為正常狀態,更新其在索引庫中的資料
            try {
                write(searchResult);  //這個方法在之前的一鍵匯入時,就已經封裝好了。可以在之前的一鍵匯入索引庫文章中檢視該方法
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else{
            try {
                //說明商品狀態為下架或者刪除,執行刪除索引庫操作
                solrServer.deleteById(itemId.toString());
                //提交刪除操作
                solrServer.commit();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

(4)書寫Mapper介面和對映檔案(mybatis相關)

    /**
     * 根據ID查詢商品
     * @auther: xushuai
     * @date: 2018/5/26 15:41
     * @return: 索引庫結果物件
     */
    SearchResult getItemById(Long itemId);
	<!--按查詢商品,返回索引結果物件-->
	<select id="getItemById" parameterType="long" resultType="cn.e3mall.common.entity.SearchResult">
		SELECT
			a.id,
			a.title,
			a.sell_point,
			a.price,
			a.image,
			b.`name` category_name
		FROM
			tb_item a
		LEFT JOIN tb_item_cat b ON a.cid = b.id
		WHERE
		a. `status` = 1 AND a.id=#{itemId}
	</select>