当前位置: 首页 > news >正文

若依线程池多线程并发 ruoyi-vue SpringBoot 实战批量发送微信小程序订阅消息

业务代码

    private final ThreadPoolTaskExecutor executorService = SpringUtils.getBean("threadPoolTaskExecutor");@Overridepublic void batchSendWxMsgByDiy(sendDiyWxMsgVo entity) {if (CollectionUtils.isEmpty(entity.getAcceptIds())) {throw new TipUserException("接收人不能为空");}if (StringUtils.isBlank(entity.getDataType())) {throw new TipUserException("类型不能为空");}List<TrainSignupMan> signupManList = signupManMapper.selectByIds(entity.getAcceptIds());if (CollectionUtils.isEmpty(signupManList)) {throw new TipUserException("人员删除或不可见");}Map<String, SysDictData> templateConfig = dictTypeService.selectDictDataByType("train_wx_learn_notice").stream().collect(Collectors.toMap(SysDictData::getDictLabel, o -> o));if (MapUtils.isEmpty(templateConfig)) {throw new TipUserException("请联系管理员配置微信消息模板-培训学习通知");}List<Long> lyUserIdIds = signupManList.stream().map(TrainSignupMan::getLyUserId).collect(Collectors.toList());if (CollectionUtils.isEmpty(lyUserIdIds)) {return;}Map<Long, TzLyUser> tzLyUserMap = tzLyUserService.selectOpenIdListByUserIds(lyUserIdIds).stream().collect(Collectors.toMap(TzLyUser::getId, o -> o));if (MapUtils.isEmpty(tzLyUserMap)) {return;}String className = entity.getClassName();String dataTip = null;Date dataTime = null;if (StringUtils.equals(entity.getDataType(), "diy")) {dataTip = entity.getDataTip();dataTime = entity.getDataTime();if (StringUtils.isBlank(dataTip)) {throw new TipUserException("温馨提示不能为空");}if (ObjectUtils.isEmpty(dataTime)) {throw new TipUserException("时间不能为空");}} else if (StringUtils.equals(entity.getDataType(), "dict")) {dataTime = DateUtils.getNowDate();SysDictData defaultSysDictData = templateConfig.get("default");SysDictData trainSysDictData = templateConfig.get(entity.getTrainingCourseId());if (ObjectUtils.isEmpty(defaultSysDictData)) {throw new TipUserException("请配置该培训班-培训学习通知默认模板");}dataTip = defaultSysDictData.getDictValue();if (ObjectUtils.isNotEmpty(trainSysDictData)) {dataTip = trainSysDictData.getDictValue();}} else {throw new TipUserException("请携带类型参数");}// 创建 final 变量副本用于 lambda 表达式final String finalDataTip = dataTip;final Date finalDataTime = dataTime;ConcurrentLinkedQueue<SmsPreventBody> smsPreventBodyQueue = new ConcurrentLinkedQueue<>();CountDownLatch latch = new CountDownLatch(signupManList.size());for (TrainSignupMan signupMan : signupManList) {TzLyUser tzLyUser = tzLyUserMap.get(signupMan.getLyUserId());if (ObjectUtils.isEmpty(tzLyUser)) {latch.countDown();} else {try {executorService.execute(()->{SmsPreventBody smsPreventBody = sendNoticeWxMsg(signupMan, templateConfig, tzLyUser.getOpenId(), className, finalDataTip, finalDataTime);smsPreventBodyQueue.add(smsPreventBody);latch.countDown();});} catch (Exception e) {latch.countDown();}}}executorService.shutdown();List<SmsPreventBody> smsPreventBodyList = new ArrayList<>(smsPreventBodyQueue);smsPreventService.saveBatch(smsPreventBodyList);}

微信发送消息工具类

   private SmsPreventBody sendNoticeWxMsg(TrainSignupMan signupMan, Map<String, SysDictData> templateConfig, String openId, String className, String dataTip, Date dataTime) {String env_version = ConfigUtils.getString("wx.mp.is.env.version", "release");SendMessageTemplateVo messageTemplateVo = new SendMessageTemplateVo();messageTemplateVo.setMiniprogram_state(env_version);messageTemplateVo.setTemplate_id(templateConfig.get("template_id").getDictValue());messageTemplateVo.setPage(templateConfig.get("page").getDictValue());messageTemplateVo.setTouser(openId);// 培训班messageTemplateVo.putParam("thing1", className);// 时间String dateFormat = DateUtil.format(dataTime, "yyyy年MM月dd日");messageTemplateVo.putParam("time2", dateFormat);// 温馨提示messageTemplateVo.putParam("thing3", dataTip);// 消息发送成功SmsPreventBody smsPreventBody = new SmsPreventBody();smsPreventBody.setMobile(signupMan.getTel());smsPreventBody.setType("train-notice");smsPreventBody.setTipStr("微信订阅消息-培训学习通知");com.alibaba.fastjson.JSONObject jsonObject = WeChatUtils.sendWxMessage(messageTemplateVo);String errcode = jsonObject.getString("errcode");String errmsg = jsonObject.getString("errmsg");if (StringUtils.equals(errcode, "0")) {smsPreventBody.setState("success");smsPreventBody.setContent(errmsg);} else {smsPreventBody.setState("error");smsPreventBody.setContent(errcode + ":" + errmsg);}return smsPreventBody;}

消息实体

package com.huida.tzly.domain.vo;import com.alibaba.fastjson.JSONObject;
import lombok.Data;import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;/*** 微信发送订阅消息**/
@Data
public class SendMessageTemplateVo implements Serializable {//接收者(用户)的 openidprivate String touser;//所需下发的订阅模板idprivate String template_id;//点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转private String page;//模板内容,格式形如 { "key1": { "value": any }, "key2": { "value": any } }的objectprivate JSONObject data = new JSONObject();// 跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版private String miniprogram_state;//进入小程序查看”的语言类型,支持zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),默认为zh_CN
//    private String lang;public void putParam(String key, String value) {Map<String, Object> temp = new HashMap<>();temp.put("value", value);this.data.put(key, temp);}}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • QT 的 QSettings 读写 INI 文件的示例
  • 前后端分离时代的SEO实践经验
  • facebook广告效果下降,可能是进入了疲劳期
  • 数据洞察力的魔法:自然语言处理在数据分析中的应用
  • ASP.NET Core Web API中实现缓存
  • Java设计模式-策略模式
  • 无人机培训机构培训计划详解
  • Excel VBA批量获取文件夹内文件名及重命名文件教程
  • 音频进阶学习一——模拟信号和数字信号
  • 8.6.数据库基础技术-数据库的控制
  • LVS理论知识
  • 软件设计之MySQL(1)
  • Oracle(62)什么是内存优化表(In-Memory Table)?
  • 【数据结构】在链式存储结构上建立一棵二叉树的算法
  • 日撸Java三百行(day22:二叉树的存储)
  • php的引用
  • centos安装java运行环境jdk+tomcat
  • css系列之关于字体的事
  • Java 9 被无情抛弃,Java 8 直接升级到 Java 10!!
  • javascript数组去重/查找/插入/删除
  • magento 货币换算
  • 订阅Forge Viewer所有的事件
  • 算法-插入排序
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • C# - 为值类型重定义相等性
  • Java数据解析之JSON
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • 移动端高清、多屏适配方案
  • ​​​​​​​GitLab 之 GitLab-Runner 安装,配置与问题汇总
  • # 深度解析 Socket 与 WebSocket:原理、区别与应用
  • #Linux杂记--将Python3的源码编译为.so文件方法与Linux环境下的交叉编译方法
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (2022版)一套教程搞定k8s安装到实战 | RBAC
  • (3)STL算法之搜索
  • (C)一些题4
  • (done) NLP “bag-of-words“ 方法 (带有二元分类和多元分类两个例子)词袋模型、BoW
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (译)2019年前端性能优化清单 — 下篇
  • (转)大型网站的系统架构
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全
  • .NET Core MongoDB数据仓储和工作单元模式封装
  • .NET Framework 3.5中序列化成JSON数据及JSON数据的反序列化,以及jQuery的调用JSON
  • .net Stream篇(六)
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • .NET中的Exception处理(C#)
  • .Net转Java自学之路—SpringMVC框架篇六(异常处理)
  • @DataRedisTest测试redis从未如此丝滑
  • @Resource和@Autowired的区别
  • @开发者,一文搞懂什么是 C# 计时器!
  • @软考考生,这份软考高分攻略你须知道
  • [].shift.call( arguments ) 和 [].slice.call( arguments )
  • [ACL2022] Text Smoothing: 一种在文本分类任务上的数据增强方法
  • [BZOJ] 1001: [BeiJing2006]狼抓兔子