RabbitMQ學習系列:五、RabbitMQ整合Spring

最後學習一下RabbitMQ如何整合Spring,畢竟現在大多是使用框架來做項目。這篇主要使用的方式是XML配置。

介紹

RabbitMQ整合Spring的學習中,搭了兩個web項目,一個作爲客戶端,一個作爲服務端,放在一個項目中也可以實現效果,但畢竟RabbitMQ也是在這種類似的環境中使用的。客戶端會把info類型和error類型的日誌發送給RabbitMQ,RabbitMQ根據所定義的路由與綁定的key分別把日誌消息傳遞給不同的隊列。
客戶端項目結構:
rabbitmq整合Spring項目結構

客戶端實現

RabbitMQ配置文件

config.properties

# RabbitMQ config
rabbitmq.host=localhost
rabbitmq.username=guest
rabbitmq.password=guest
rabbitmq.port=5672

這裏在我本機的RabbitMQ,如果是在遠程主機上則要做相應修改。需要注意的是,我們訪問RabbitMQ管理界面是使用的15672端口,但通過連接訪問RabbitMQ是使用5672端口

XML配置


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:rabbit="http://www.springframework.org/schema/rabbit"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
                           http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.7.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
                           http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
                           http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">

    <context:component-scan base-package="com.rabbitmq.spring"/>
    <context:property-placeholder location="classpath*:config.properties"/>
    <mvc:annotation-driven />
    <mvc:default-servlet-handler/>
    <!--連接工廠-->
    <rabbit:connection-factory id="connectionFactory" host="${rabbitmq.host}" username="${rabbitmq.username}" password="${rabbitmq.password}" port="${rabbitmq.port}"></rabbit:connection-factory>
    <!--RabbitAdmin主要用於創建隊列和交換器以及綁定關係等。-->
    <rabbit:admin id="rabbitAdmin" connection-factory="connectionFactory"/>
    <!--聲明隊列-->
    <rabbit:queue name="rabbitmq_log_info" durable="true" auto-delete="false"  />
    <rabbit:queue name="rabbitmq_log_error" durable="true" auto-delete="false" />
    <!--聲明路由並綁定隊列,指定routingKey-->
    <rabbit:direct-exchange name="hap.log.exchange"  auto-delete="false" durable="true">
        <rabbit:bindings>
            <rabbit:binding queue="rabbitmq_log_info" key="info"></rabbit:binding>
            <rabbit:binding queue="rabbitmq_log_error" key="error"></rabbit:binding>
        </rabbit:bindings>
    </rabbit:direct-exchange>
    <!--定義RabbitTemplate,用於發送與接收消息-->
    <rabbit:template id="rabbitTemplateLogInfo" connection-factory="connectionFactory" routing-key="info" exchange="hap.log.exchange" message-converter="jsonMessageConverter"></rabbit:template>
    <rabbit:template id="rabbitTemplateLogError" connection-factory="connectionFactory" routing-key="error" exchange="hap.log.exchange" message-converter="jsonMessageConverter"></rabbit:template>

    <!-- 消息對象json轉換類 -->
    <bean id="jsonMessageConverter" class="org.springframework.amqp.support.converter.Jackson2JsonMessageConverter" />
</beans>

rabbit-admin 標籤如不聲明,則 rabbit:queue 與 rabbit:direct-exchange 標籤中必須添加 auto-declare 屬性爲true ,表示如果隊列或路由不存在則自動聲明,如不聲明rabbit-admin,也不添加auto-declare屬性則啓動時會報聲明隊列錯誤,或隊列不存在。
rabbit:template 標籤中的routing-key、exchange也可以不在XML中配置,在類中發送消息時可以作爲參數代入。則XML中只需要配置一個rabbit:template標籤即可

Service

Service接口

public interface ISendMessageService {
    public void sendInfoMessage(String message);

    public void sendErrorMessage(String message);
}

Service實現類

@Service
public class SendMessageService implements ISendMessageService{

    @Autowired
    @Qualifier("rabbitTemplateLogInfo")
    public RabbitTemplate rabbitTemplateLogInfo;

    @Autowired
    @Qualifier("rabbitTemplateLogError")
    private RabbitTemplate rabbitTemplateLogError;

    @Override
    public void sendInfoMessage(String message) {
        System.out.println("Info發送消息中>>>" + message);
        this.rabbitTemplateLogInfo.convertAndSend(message);
    }

    @Override
    public void sendErrorMessage(String message) {
        System.out.println("Error發送消息中>>>" + message);
        this.rabbitTemplateLogError.convertAndSend(message);
    }
}

RabbitTemplate的convertAndSend方法中,如果XML中已經配置好了對應的exchange與routingKey則可以直接傳入一個消息進行發送即可。如果沒有可以在參數中加入Exchange 與 routingkey

Controller

@Controller
@RequestMapping("/rabbitmqLog")
public class RabbitmqController {

    @Autowired
    @Qualifier("sendMessageService")
    ISendMessageService service = new SendMessageService();


    @RequestMapping(value = "/sendInfoLog",method = RequestMethod.GET)
    public void sendInfoMessage(String message){
        service.sendInfoMessage(message);
    }

    @RequestMapping("/sendErrorLog")
    public void sendErrorMessage(String message){
        service.sendErrorMessage(message);
    }

}

服務端實現

因爲這裏只是做一個簡單的示例,所以服務端只做了監聽,沒有做什麼業務邏輯。

RabbitMQ配置文件

這裏與客戶端是一樣的

XML配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:rabbit="http://www.springframework.org/schema/rabbit"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
                           http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.7.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
                           http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
                           http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">


    <context:component-scan base-package="com.rabbitmq.spring"/>
    <context:property-placeholder location="classpath*:config.properties"/>
    <mvc:annotation-driven />
    <mvc:default-servlet-handler/>
    <rabbit:connection-factory id="connectionFactory" host="${rabbitmq.host}" username="${rabbitmq.username}" password="${rabbitmq.password}" port="${rabbitmq.port}"></rabbit:connection-factory>
    <rabbit:admin id="rabbitAdmin" connection-factory="connectionFactory"/>
    <rabbit:queue name="rabbitmq_log_info" durable="true" auto-delete="false" />
    <rabbit:queue name="rabbitmq_log_error" durable="true" auto-delete="false" />

    <rabbit:listener-container connection-factory="connectionFactory" acknowledge="auto">
        <rabbit:listener ref="messageRecevicer" queues="rabbitmq_log_info"/>
        <rabbit:listener ref="messageRecevicer" queues="rabbitmq_log_error"/>
    </rabbit:listener-container>

    <bean id="messageRecevicer" class="com.rabbitmq.spring.listener.QueueListener"/>

    <!-- 消息對象json轉換類 -->
    <bean id="jsonMessageConverter" class="org.springframework.amqp.support.converter.Jackson2JsonMessageConverter" />
</beans>

服務端的XML與客戶端不同的是多了監聽配置與監聽類的Bean,少了路由聲明與隊列綁定的配置。

監聽類

@Component
public class QueueListener implements MessageListener{
    @Override
    public void onMessage(Message message) {
        String msg = null;
        try {
            msg = new String(message.getBody(),"UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        System.out.println("監聽到 "+ message.getMessageProperties().getConsumerQueue()+" 隊列消息:" + msg);
    }
}

測試

最後我們分別啓動客戶端與服務端。客戶端調用Controller向服務端發送消息 。
測試

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