ال الگوی مسیریابی RabbitMQ (حالت مستقیم) در جاوا از نوع تبادل DirectExchange استفاده می‌کند. تفاوت آن با الگوی انتشار-اشتراک در این است که تبادل مستقیم (Direct exchange) پیام‌ها را به صف‌ها با پارامترهای مسیریابی که کاملاً مطابقت دارند، ارسال می‌کند. ساختار به شکل تصویر زیر است:

RabbitMQ حالت مستقیم

نکته: بدون توجه به حالت کاری که از آن استفاده می‌شود، تفاوت در نوع تبادل استفاده شده و پارامترهای مسیریابی است.

1. آموزش‌های پیش‌نیاز

لطفاً بخش‌های زیر را بخوانید تا دانش مربوطه را درک کنید:

2. تعریف تبادل مستقیم

در Spring AMQP، کلاس متناظر با تبادل مستقیم DirectExchange است. ما تبادل را از طریق یک کلاس پیکربندی Spring Boot تعریف می‌کنیم.

package com.tizi365.rabbitmq.config;

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QueueConfig {
	@Bean
    public DirectExchange direct() {
        // تعریف تبادل
        // پارامتر نام تبادل است، که باید یکتا باشد
        return new DirectExchange("tizi365.direct");
    }
}

نکته: هم فرستنده پیام و هم گیرنده نیاز به یک تبادل دارند.

3. ارسال پیام‌ها

ما پیام‌ها را به تبادل ارسال می‌کنیم که سپس پیام‌ها را بر اساس قوانین مسیریابی به صف‌های مربوطه ارسال می‌کند.

package com.tizi365.rabbitmq.service;

import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Service
public class SendService {
    @Autowired
    private RabbitTemplate template;
    @Autowired
    private DirectExchange direct;

    // برای نمایش، ما از یک وظیفه زمان‌بندی شده برای ارسال یک پیام در هر ثانیه استفاده می‌کنیم
    @Scheduled(fixedDelay = 1000, initialDelay = 1000)
    public void send() {
        // محتوای پیام
        String message = "Hello World!";
        // ارسال پیام
        // پارامتر اول نام تبادل است
        // پارامتر دوم کلید مسیریابی است. در یک تبادل مستقیم، پیام به صف ارسال می‌شود که کلید مسیریابی آن "tizi365" مطابقت دارد
        // پارامتر سوم محتوای پیام است که هر نوعی را پشتیبانی می‌کند تا بتواند سریالیزه شود
        template.convertAndSend(direct.getName(), "tizi365", message);
        System.out.println("پیام '" + message + "' ارسال شد");
    }
}

نکته: به پارامتر دوم در متد convertAndSend توجه کنید، زیرا این یک پارامتر حیاتی است.

4. دریافت پیام‌ها

4.1 تعریف صف‌ها و متصل کردن Exchange

برای مصرف کردن پیام‌ها از یک صف، ابتدا باید یک صف را تعریف کرده و سپس آن را به تبادل مورد نظر متصل کنید. کد زیر دو صف را تعریف کرده و آن‌ها را به همان تبادل متصل می‌کند:

package com.tizi365.rabbitmq.config;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QueueConfig {
    @Bean
    public DirectExchange direct() {
        // تعریف تبادل
        // پارامتر نام تبادل است که باید یکتا باشد
        return new DirectExchange("tizi365.direct");
    }

    @Bean
    public Queue queue1() {
        // تعریف صف 1
        return new Queue("tizi365.direct.queue1");
    }

    @Bean
    public Queue queue2() {
        // تعریف صف 2
        return new Queue("tizi365.direct.queue2");
    }

    @Bean
    public Binding binding1(DirectExchange direct, Queue queue1) {
        // تعریف یک اتصال برای متصل کردن صف 1 به تبادل مستقیم با یک کلید مسیری با نام "tizi365"
		// هنگامی که کلید مسیری با نام "tizi365" همخوانی داشته باشد، تبادل پیام‌ها را به صف 1 ارسال می‌کند
        return BindingBuilder.bind(queue1).to(direct).with("tizi365");
    }

    @Bean
    public Binding binding2(DirectExchange direct, Queue queue2) {
        // تعریف یک اتصال برای متصل کردن صف 2 به تبادل مستقیم با یک کلید مسیری با نام "baidu"
		// هنگامی که کلید مسیری با نام "baidu" همخوانی داشته باشد، تبادل پیام‌ها را به صف 2 ارسال می‌کند
        return BindingBuilder.bind(queue2).to(direct).with("baidu");
    }
}

4.2 تعریف گوش کننده‌های صف

استفاده از انوتیشن RabbitListener برای تعریف گوش کنندگان پیام جهت مصرف پیام‌ها از صف‌های خاص:

package com.tizi365.rabbitmq.listener;

import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;

// اجازه دهید اسپرینگ کلاس فعلی را مدیریت کند
@Component
public class DemoListener {
    // تعریف یک گوش کننده برای مصرف پیام‌ها از صف 1
    @RabbitListener(queues = "tizi365.direct.queue1")
    public void receive1(String msg) {
        System.out.println("پیام از صف 1 دریافت شد: " + msg);
    }

    // تعریف یک گوش کننده برای مصرف پیام‌ها از صف 2
    @RabbitListener(queues = "tizi365.direct.queue2")
    public void receive2(String msg) {
        System.out.println("پیام از صف 2 دریافت شد: " + msg);
    }
}

از آنجا که تنها صف 1 یک کلید مسیری به نام "tizi365" هنگام متصل شدن به تبادل دارد، فقط صف 1 می‌تواند پیام دریافت کند. صف 2، به دلیل عدم همخوانی کلید مسیری، هیچ پیامی دریافت نمی‌کند.