1、依赖

  <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
        </dependency>

 2、配置

spring:
cloud:
stream:
rocketmq:
binder:
name-server: ${ROCKETMQ_NAME_SERVER:192.168.3.22:30094} # RocketMQ NameServer地址
enable-msg-trace: true
bindings:
buryingPointOutput:
destination: burying-point-topic # 生产者的Topic
group: burying-point-product-group # 生产者的Group
producer:
partitionKeyExtractorName: buryingPointQueueSelector
buryingPointInput:
destination: burying-point-topic # 消费者的Topic
group: burying-point-consumer-group1 # 消费者的Group

 3、定义生产

import org.springframework.cloud.stream.annotation.Output;
import org.springframework.messaging.MessageChannel;

public interface HelpAiLogSource {
    String HELP_AI_LOG_OUTPUT = "helpAiLogOutput";

    @Output(HELP_AI_LOG_OUTPUT)
    MessageChannel helpAiLogOutput();
}
import jnpf.helpailog.config.HelpAiLogSource;
import jnpf.model.helpailog.po.FtbHelpAiChatLog;
import org.apache.rocketmq.common.message.MessageConst;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

@Service
@EnableBinding(HelpAiLogSource.class)
public class HelpAiLogProducer {

    @Autowired
    private HelpAiLogSource helpAiLogSource;

    public void sendMessage(FtbHelpAiChatLog dto) {
        //怎么给消息打上tag
boolean send = helpAiLogSource.buryingPointOutput().send(MessageBuilder.withPayload(dto)
.setHeader(MessageConst.PROPERTY_TAGS, dto.getTenantId() + "," + dto.getUserId())
.setHeader("partitionKey", dto.getFrontKey()) // frontKey作为PROPERTY_KEYS发送
.build());
     }
}

4、定义消费

import org.springframework.cloud.stream.annotation.Input;
import org.springframework.messaging.SubscribableChannel;

public interface HelpAiLogSink {
    String HELP_AI_LOG_INPUT = "helpAiLogInput";

    @Input(HELP_AI_LOG_INPUT)
    SubscribableChannel helpAiLogInput();
}
import cn.hutool.json.JSONUtil;
import jnpf.base.UserInfo;
import jnpf.config.ConfigValueUtil;
import jnpf.database.util.TenantDataSourceUtil;
import jnpf.exception.LoginException;
import jnpf.helpailog.config.HelpAiLogSink;
import jnpf.helpailog.service.FtbHelpAiChatLogService;
import jnpf.model.helpailog.po.FtbHelpAiChatLog;
import jnpf.util.StringUtil;
import jnpf.util.UserProvider;
import jnpf.util.data.DataSourceContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

@Service
@Slf4j
@EnableBinding(HelpAiLogSink.class)
public class HelpAiLogConsumer {

    @Autowired
    private FtbHelpAiChatLogService ftbHelpAiChatLogService;

    @Autowired
    private ConfigValueUtil configValueUtil;

    @StreamListener(HelpAiLogSink.HELP_AI_LOG_INPUT)
    public void receive(String message) {
        FtbHelpAiChatLog entity = JSONUtil.toBean(message, FtbHelpAiChatLog.class);
        log.info("0000000接收到消息:{}", message);
        switchTenant(entity.getTenantId());
        ftbHelpAiChatLogService.record(entity);
    }

    private void switchTenant(String tenantId) {
        // 判断是否为多租户
        if (configValueUtil.isMultiTenancy()) {
            // 判断是不是从外面直接请求
            if (StringUtil.isNotEmpty(tenantId)) {
                //切换成租户库
                try {
                    TenantDataSourceUtil.switchTenant(tenantId);
                } catch (LoginException e) {
                    throw new RuntimeException("切换租户失败");
                }
            } else {
                UserInfo userInfo = UserProvider.getUser();
                Assert.notNull(userInfo.getUserId(), "缺少租户信息");
                DataSourceContextHolder.setDatasource(userInfo.getTenantId(), userInfo.getTenantDbConnectionString(), userInfo.isAssignDataSource());
            }
        }
    }
}

5、定义测试接口

    @Autowired
    private HelpAiLogProducer helpAiLogProducer;

    @Autowired
    private UserProvider userProvider;

    @Autowired
    private FtbHelpAiChatLogService ftbHelpAiChatLogService;

    /**
     * @param dto
     * @return
     */
    @PostMapping("/record")
    public ActionResult<Boolean> record(@Validated @RequestBody HelpAiLogDto dto) {

        try {
            UserInfo userInfo = userProvider.get();
            String userId = userInfo.getUserId();
            String tenantId = userInfo.getTenantId();
            helpAiLogProducer.sendMessage(dto.convertToEntity(userId, tenantId));
        } catch (Exception e) {
            e.printStackTrace();
            log.error("帮助ai 聊天记录异常:{},{}", dto, e);
        }
        return ActionResult.success();
    }

 定义队列选择器

package jnpf.buryingpoint.config;


import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.stream.binder.PartitionKeyExtractorStrategy;
import org.springframework.cloud.stream.binder.PartitionSelectorStrategy;
import org.springframework.stereotype.Component;

@Slf4j
@Component("buryingPointQueueSelector")
public class BuryingPointQueueSelector implements PartitionSelectorStrategy, PartitionKeyExtractorStrategy {


    @Override
    public int selectPartition(Object key, int partitionCount) {
        int id = key.hashCode();
        int index = id % partitionCount;
        return index;
    }

    @Override
    public Object extractKey(org.springframework.messaging.Message<?> message) {
        if (message.getHeaders().containsKey("partitionKey")) {
            return message.getHeaders().get("partitionKey");
        }
        return null;
    }
}