RabbitMq+SpringBoot实现站内消息分发

导入依赖

        <!--rabbitmq-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.amqp</groupId>
            <artifactId>spring-rabbit-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

配置文件(记得开启手动确认,不然会默认自动确认,导致确认两次报错)

spring.rabbitmq.host=
spring.rabbitmq.port=5672
spring.rabbitmq.username=
spring.rabbitmq.password=
#手动确认
spring.rabbitmq.listener.simple.acknowledge-mode=manual
#开启交换机确认消息
spring.rabbitmq.publisher-confirm-type=correlated

配置rabbitmq包括交换机,队列;routingKey,以及绑定备份交换机备用。

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

@Configuration
public class RabbitMqConfig {
    //站内信队列名
    public static final String QUEUE_SYSTEM = "queue_system";
    //交换机名称
    public static final String EXCHANGE_TOPIC = "exchange_topic";
    //备份交换机
    public static final String BACKUP_EXCHANGE_NAME = "backup_exchange";
    //备份队列
    public static final String BACKUP_QUEUE_NAME = "backup_queue";
    @Bean
    public FanoutExchange backupExchange() {
        return new FanoutExchange(BACKUP_EXCHANGE_NAME);
    }

    @Bean
    public Queue backupQueue() {
        return new Queue(BACKUP_QUEUE_NAME);
    }


    @Bean("topicExchange")
    public TopicExchange topicExchange(){
        return ExchangeBuilder.topicExchange(EXCHANGE_TOPIC).withArgument("alternate-exchange",BACKUP_EXCHANGE_NAME).durable(true).build();
    }
    @Bean("queueSystem")
    public Queue queueSystem(){
        return new Queue(QUEUE_SYSTEM,true,false,false);
    }
    @Bean
    public Binding queueSystemBindingTopicExchange(@Qualifier("topicExchange") TopicExchange topicExchange,
                                                   @Qualifier("queueSystem") Queue queueSystem){
        return BindingBuilder.bind(queueSystem).to(topicExchange).with("msgSystem");
    }
    @Bean
    public Binding backupQueueBindingBackupExchange(@Qualifier("backupExchange") FanoutExchange backupExchange,
                                                    @Qualifier("backupQueue") Queue backupQueue) {
        return BindingBuilder.bind(backupQueue).to(backupExchange);
    }


}

配置交换机,队列异步确认

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

@Configuration
@Slf4j
public class ConfirmCallBack implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnsCallback {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @PostConstruct
    public void init() {
        //注入这个实现后的这个方法类
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnsCallback(this);
    }

    @Override
    //异步监听交换机
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if (ack) {
            log.info("交换机已经收到id为" + correlationData.getId() + "的消息");
        } else {
            log.info("交换机未收到id为" + correlationData.getId() + "的消息,原因是:" + cause);
        }
    }

    @Override//异步监听队列,路由失败,不可达目的地则回退
    public void returnedMessage(ReturnedMessage returned) {
        log.error("消息{},被交换机{}因退回,退回原因:{},路由key:{}",
                new String(returned.getMessage().getBody()),
                returned.getExchange(),
                returned.getReplyText(),//cause
                returned.getRoutingKey());
    }
}

消息发送service层(发布,回显,写入)

public interface MsgSystemService {
    void sendMessage(String msg);
    PaginationDTO list(Integer page, Integer size);
    void createMessage(Message message);
}

实现类

import life.majiang.community.config.ConfirmCallBack;
import life.majiang.community.config.RabbitMqConfig;
import life.majiang.community.dto.PaginationDTO;
import life.majiang.community.mapper.MessageMapper;
import life.majiang.community.model.Message;
import life.majiang.community.model.MessageExample;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.RowBounds;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.UUID;

@Service
@Slf4j
public class MsgSystemServiceImp  implements MsgSystemService{
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private MessageMapper messageMapper;
    @Autowired
    private ConfirmCallBack confirmCallBack;
    @Override
    public void sendMessage(String msg) {
        CorrelationData correlationData=new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(RabbitMqConfig.EXCHANGE_TOPIC,"msgSystem", msg,correlationData);
        log.info("发送成功,消息内容:{}",msg);
    }

    @Override
    public PaginationDTO list(Integer page, Integer size) {
        //泛型
        PaginationDTO<Message> paginationDTO = new PaginationDTO<>();

        Integer totalPage;
        //通知数量
        Integer totalCount = (int) messageMapper.countByExample(null);

        if (totalCount % size == 0) {
            totalPage = totalCount / size;
        } else {
            totalPage = totalCount / size + 1;
        }

        if (page < 1) {
            page = 1;
        }
        if (page > totalPage) {
            page = totalPage;
        }
        paginationDTO.setPagination(totalPage, page);

        //加分页
        Integer offset = size * (page - 1);
        MessageExample example = new MessageExample();
        //时间倒序输出
        example.setOrderByClause("gmt_create desc");
        List<Message> messages = messageMapper.selectByExampleWithBLOBsWithRowbounds(example, new RowBounds(offset, size));
        //内容做个判断
        if (messages.size() == 0) {
            return paginationDTO;
        }
        paginationDTO.setData(messages);
        return paginationDTO;
    }

    @Override
    public void createMessage(Message message) {
        Message msg = new Message();
        msg.setGmtCreate(System.currentTimeMillis());
        msg.setMsg(message.getMsg());
        messageMapper.insert(msg);
    }
}

controller发送

@Controller
@Slf4j
public class MsgSystemController {
    @Autowired
    private MsgSystemService msgSystemService;

    @GetMapping("/sendMessage")
    public String SendMessage() {
        return "sendMessage";
    }

    @PostMapping("/sendMessage")
    public String doSendMessage(String message,
                                HttpServletRequest request,
                                Model model) {
        //向所有用户发送消息
        User user = (User) request.getSession().getAttribute("user");
        if (user.getId() == 1) {
            if (message == null || message == "") {
                model.addAttribute("error", "信息不能为空");
                return "sendMessage";
            }
            model.addAttribute("message", message);
            msgSystemService.sendMessage(message);
        }
        //发完返回首页
        return "redirect:/";
    }
}

用户接收(消费并写入数据库)

@Component
@Slf4j
public class MsgSystemConsumer {
    @Autowired
    private MsgSystemService msgSystemService;
    @RabbitListener(queues = RabbitMqConfig.QUEUE_SYSTEM)
    public void listenerPMsg(Message message, Channel channel) throws IOException {
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            String msg = new String(message.getBody());
            log.info("用户收到站内通知:{}", msg);
            channel.basicAck(deliveryTag,false);
            //写入数据库
            life.majiang.community.model.Message message1 = new life.majiang.community.model.Message();
            message1.setMsg(msg);
            msgSystemService.createMessage(message1);
        }catch (Exception e){
            channel.basicReject(deliveryTag,false);
            e.printStackTrace();
        }
    }
}

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值