springboot+消息队列

1.创建msg文件夹,在里面添加下面几个java文件

MsgQueueConstant:
package com.panku.msg;

import java.util.concurrent.Semaphore;

/**
 * @program: hycloudoa
 * @description:
 * @author: xwf
 * @create: 2020-06-24 16:15
 **/
public class MsgQueueConstant {

    /**
     * 最大队列数量
     */
    public final static int MAX_QUEUE = 1000;

    /**
     * 队列中最少成员数
     */
    public final static int MIN_Count = 10;

    /**
     * 生产者信号量 锁,用于系统消息挂起和通知
     */
    public  static Semaphore producerSemaphore = new Semaphore(1);

    /**
     * 消费者信号量 锁,用于系统消息挂起和通知
     */
    public  static Semaphore cosumerSemaphore = new Semaphore(0);


}
SysMsgQueue:
package com.panku.msg;

import com.panku.core.entity.BizMsg;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;

/**
 * @program: hycloudoa
 * @description: 系统消息队列,
 * 采用无界队列LinkedBlockingQueue:是一个由链表结构组成的双向阻塞队列,即可以从队列的两端插入和移除元素
 * @author: xwf
 * @create: 2020-06-24 15:06
 **/
@Component
public class SysMsgQueue {

    /**
     * 存放系统消息, 采用无界队列LinkedBlockingQueue:是一个由链表结构组成的双向阻塞队列,即可以从队列的两端插入和移除元素
     */
    private BlockingQueue<BizMsg> bizMsgQueue
            = new LinkedBlockingDeque<>(MsgQueueConstant.MAX_QUEUE);


    /**
     * 批量添加队列消息
     * @param bizMsgs
     */
    public void addAll(List<BizMsg> bizMsgs) {
        bizMsgQueue.addAll(bizMsgs);
    }


    /**
     * 移除并返回列头部元素,如队列为空阻塞
     * @return
     * @throws InterruptedException
     */
    public BizMsg take() throws InterruptedException {
        return bizMsgQueue.take();
    }

    /**
     * //获取并移除此队列的头,如果此队列为空,则返回 null。
     * @return
     */
    public BizMsg poll(){
        return bizMsgQueue.poll();
    }

    /**
     * 返回当前队列成员数量
     * @return
     */
    public Integer count(){
        return bizMsgQueue.size();
    }
}
SysMsgQueueCosumer:
package com.panku.msg;



import com.alibaba.fastjson.JSONObject;
import com.panku.core.entity.BizMsg;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @program: hycloudoa
 * @description: 系统消息消费者
 * @author: xwf
 * @create: 2020-06-24 15:17
 **/
@Component
@Slf4j
public class SysMsgQueueCosumer implements Runnable {


    @Autowired
    private SysMsgQueue sysMsgQueue;



    private Thread thread;

    public void init() {
        thread = new Thread(this, "MsgCosumer");
        thread.start();
    }

    @Override
    public void run() {
        //阻塞,等待生产者生产数据,继续执行
        try {
            MsgQueueConstant.cosumerSemaphore.acquire();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        while (true) {
            try {
                execute();
                TimeUnit.MILLISECONDS.sleep(200);
            } catch (Exception e) {
                e.printStackTrace();
                log.info("消费者发生异常:{}", e.getMessage());
            }
        }
    }

    /**
     * 消费消息
     */
    private void execute() {
        BizMsg msg = sysMsgQueue.poll();
        //获取队列消息,如消息为null,则释放lock锁,继续队列添加消息
        if (msg != null) {
            log.info("--------开始消费消息{}", JSONObject.toJSONString(msg));
          /*  log.info("--------开始消费消息{}", JSONObject.toJSONString(msg));
            //根据消息类型发送对应的消息
            if (msg.getMsgType() == 1) {//发送短信
                try {
                    //判断是否发送消息
                    if (SysParamInfo.getParamVal(Constants.IF_SEND_SMS).equals("1")) {
                        //将长连接转为短连接
                        String simpleUrl = SimpleUrlUtil.getSimpleUrl(msg.getMsgContent());
//                        String urlParam = simpleUrl.substring(25);
                        String[] split = simpleUrl.split("/");
                        String urlParam = split[3];
                        log.info("短信参数:【{}】", urlParam);
                        SmsSingleSenderResult smsSingleSenderResult = smsSingleSender.sendWithParam("86", msg.getAcpPerson(),
                                configBean.getInvoiceTplId().intValue(), new String[]{urlParam}, null, "", "");
                        log.info("短信发送结果:{}", JSONObject.toJSONString(smsSingleSenderResult));
                        bizMsgMapper.update(null, new UpdateWrapper<BizMsg>().eq("id", msg.getId())
                                .set("send_state", 2).set("send_time", new Date()));

                    } else {
                        log.info("参数表中发送短信的配置为0,即不发送短信");
                        bizMsgMapper.update(null, new UpdateWrapper<BizMsg>().eq("id", msg.getId())
                                .set("send_state", 2).set("send_time", new Date()));
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("发送短信{}时,发生异常{}", msg.toString(), e.getMessage());
                    bizMsgMapper.update(null, new UpdateWrapper<BizMsg>().eq("id", msg.getId())
                            .set("send_state", 3).set("send_time", new Date()));
                }
            } else if (msg.getMsgType() == 2) {//发送邮件
                if (SysParamInfo.getParamVal(Constants.IF_SEND_EMAIL).equals("1")) {
                    MailBean mailBean = new MailBean();
                    mailBean.setSubject(configBean.getHospitalName() + "开票结果通知");
                    mailBean.setRecipient(msg.getAcpPerson());
                    mailBean.setContent("您的电子发票已开具,详情访问地址:" + msg.getMsgContent());
                    try {
                        mailService.sendSimpleMail(mailBean);
                        bizMsgMapper.update(null, new UpdateWrapper<BizMsg>().eq("id", msg.getId())
                                .set("send_state", 2).set("send_time", new Date()));
                    } catch (Exception e) {
                        e.printStackTrace();
                        log.info("发送邮件时出错:{}", e.getMessage(), e);
                        bizMsgMapper.update(null, new UpdateWrapper<BizMsg>().eq("id", msg.getId())
                                .set("send_state", 3).set("send_time", new Date()));
                    }

                } else {
                    log.info("参数表中发送邮件的配置为0,即不发送邮件");
                    bizMsgMapper.update(null, new UpdateWrapper<BizMsg>().eq("id", msg.getId())
                            .set("send_state", 2).set("send_time", new Date()));
                }
            }*/


        } else {
            //队列中执行完毕,通知生产者生产数据
            log.info("消费者:队列中执行完毕,通知生产者生产数据");
            MsgQueueConstant.producerSemaphore.release();
            try {
                log.info("消费者:队列中执行完毕,等待生产者生产数据");
                //阻塞,等待生产者生产数据,继续执行
                MsgQueueConstant.cosumerSemaphore.acquire();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}
SysMsgQueueProducer:
package com.panku.msg;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.panku.core.entity.BizMsg;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @program: hycloudoa
 * @description: 系统消息生产者
 * @author: xwf
 * @create: 2020-06-24 15:17
 **/
@Component
@Slf4j
public class SysMsgQueueProducer implements Runnable {

    @Autowired
    private SysMsgQueue sysMsgQueue;





    /**
     * 是否存在消息
     */
    private boolean emptyFlag = true;

    private Thread thread;

    public void init() {
        log.info("消息队列生产者服务");
        thread = new Thread(this, "MsgProducer");
        thread.start();
    }

    @Override
    public void run() {
        while (true) {
            try {
                pullData();
                TimeUnit.MILLISECONDS.sleep(200);
            } catch (Exception e) {
                e.printStackTrace();
                log.error("生产者生产数据时发生异常:{}", e.getMessage());
            }
        }
    }

    /**
     * 拉取系统未发送数据
     */
    public void pullData() {
        try {
            //使用信号量,消费信号量如信号量为0阻塞.等待通知:队列执行完毕或者有新的消息
            log.info("生产者:等待队列执行完毕或新消息");
            MsgQueueConstant.producerSemaphore.acquire();
            //此步骤为异步线程,会发生消息还没插入数据库,就会查询待发送消息,此时会查询不到。所以加阻塞等待消息插入数据库中,在查询执行
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
      /*  QueryWrapper<BizMsg> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("send_state", 1);
        queryWrapper.orderByAsc("add_time");
        IPage<BizMsg> bizMsgIPage = bizMsgMapper.selectPage(new Page<>(1, MsgQueueConstant.MAX_QUEUE), queryWrapper);
        List<BizMsg> unsentMsg = bizMsgIPage.getRecords();*/
        List<BizMsg> unsentMsg = new ArrayList<>();
        BizMsg bizMsg=new BizMsg();
        bizMsg.setId(1);
        unsentMsg.add(bizMsg);
        log.info("生产者:生产数据{}条", unsentMsg.size());
        if (!unsentMsg.isEmpty()) {
            log.info("++++++++生产消息:{}", JSONObject.toJSONString(unsentMsg));
            sysMsgQueue.addAll(unsentMsg);
            //添加信号量+1,通知消费者进行消费
            log.info("生产者:通知消费者");
            MsgQueueConstant.cosumerSemaphore.release();
        }
    }


}

2.新建config文件夹,在里面添加 SysMsgConfig.java文件

package com.panku.config.msg;


import com.panku.msg.SysMsgQueueCosumer;
import com.panku.msg.SysMsgQueueProducer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

/**
 * @program: hycloudoa
 * @description: 消息配置
 * @author: xwf
 * @create: 2020-06-28 09:04
 **/
@Configuration
public class SysMsgConfig {

    @Autowired
    private SysMsgQueueCosumer sysMsgQueueCosumer;


    @Autowired
    private SysMsgQueueProducer sysMsgQueueProducer;

    @PostConstruct
    public void init() {
        sysMsgQueueProducer.init();
        sysMsgQueueCosumer.init();
    }


}

3.启动测试

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值