使用springboot每日推送早安问候语到用户微信
本文主要实现给不同的用户推动不同的问候模板
准备工作
申请微信公众平台的测试号
申请微信测试公众号
创建成功后,可以看到appid和appsecret,这个后面认证时需要
申请模板
可自行修改
今天是:{{now.DATA}} 不管那一天,每一天都是想你的一天
当前城市:{{city.DATA}}
今天的天气:{{text.DATA}}
最低气温:{{low.DATA}} 度
最高气温:{{high.DATA}} 度
今天是我们想恋的第:{{scq_day.DATA}} 天
距你的生日还有:{{bir_day.DATA}} 天
{{daily_english_cn.DATA}}
{{daily_english_en.DATA}}
新建成功后,记得保存模板Id后续有用
扫描关注该测试公众号
扫码关注后,记录微信号,后续推送通知用
申请百度天气
申请百度天气
完成认证后,创建一个应用,保存ak
申请天行数据的接口
申请天行数据
- 申请彩虹屁
- 申请每日一句
记得保存申请接口的key
开发工作
技术栈
- springboot 2.7.5
- swagger 3.0
- mysql 8.x
- spring data jpa
- openfeign
依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.zhao</groupId><artifactId>daily-weather</artifactId><version>1.0.0</version><name>daily-weather</name><description>微信用户推送消息</description><properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.7.5</spring-boot.version><swagger.version>3.0.0</swagger.version><knife4j.version>3.0.3</knife4j.version><fastjson.version>2.0.15</fastjson.version><openfeign.version>3.1.3</openfeign.version><hutools.version>5.7.5</hutools.version></properties><dependencies><!--hutools--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-core</artifactId><version>${hutools.version}</version></dependency><!--fastjson--><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>${fastjson.version}</version></dependency><!--open feign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId><version>${openfeign.version}</version></dependency><!--weixin-java-mp--><dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-mp</artifactId><version>3.3.0</version></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--swagger--><dependency><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artifactId><version>${swagger.version}</version></dependency><!--换掉默认皮肤--><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>${knife4j.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.3.7.RELEASE</version><configuration><mainClass>com.zhao.wechat.DailyWeatherApplication</mainClass></configuration><executions><execution><id>repackage</id><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build></project>
配置文件
server:port: 43310
# 微信配置
tencent:wechat:appId: 微信appidappSecret: 微信appSecret# 模板消息集合templatelist:- type: 1templateId: 微信模板id- type: 2templateId: 微信模板id- type: 3templateId: 微信模板id
# 百度天气配置
baidu:server: https://api.map.baidu.comak: 百度数据的ak
# 天行数据
tianxin:server: http://api.tianapi.comkey: 天行数据的key
spring:mvc:pathmatch:matching-strategy: ant_path_matcherdatasource:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://ip:3306/库名?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername: rootpassword: 564929hikari:minimum-idle: 5# 空闲连接存活最大时间,默认600000(10分钟)idle-timeout: 180000# 连接池最大连接数,默认是10maximum-pool-size: 10# 此属性控制从池返回的连接的默认自动提交行为,默认值:trueauto-commit: true# 连接池名称pool-name: MyHikariCP# 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟max-lifetime: 1800000# 数据库连接超时时间,默认30秒,即30000connection-timeout: 30000connection-test-query: SELECT 1jpa:show-sql: true # 默认false,在日志里显示执行的sql语句database: mysqldatabase-platform: org.hibernate.dialect.MySQL5Dialecthibernate:ddl-auto: update #指定为update,每次启动项目检测表结构有变化的时候会新增字段,表不存在时会 新建,如果指定create,则每次启动项目都会清空数据并删除表,再新建naming:#指定jpa的自动表生成策略,驼峰自动映射为下划线格式7implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl#physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
# 日志
#logging:
# config: classpath:logback-spring-dev.xml
统一数据封装
package com.zhao.wechat.advice;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhao.wechat.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;/*** 对前端响应结果统一封装*/
@Slf4j
@RestControllerAdvice(basePackages = {"com.zhao.wechat.rest"})
public class ApiResponseAdvice implements ResponseBodyAdvice<Object> {/*** 打印统一请求响应规范*/ApiResponseAdvice(){log.info("启动请求统一响应规范... ...");}/*** 判断是否需要对返回值进行封装* @param returnType the return type* @param converterType the selected converter type* @return*/@Overridepublic boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {// 如果返回的结果是Result.class类型就不用封装if (returnType.getParameterType().equals(Result.class)){return false;}return true;}/*** 对返回前端的值统一封装* @param body the body to be written* @param returnType the return type of the controller method* @param selectedContentType the content type selected through content negotiation* @param selectedConverterType the converter type selected to write to the response* @param request the current request* @param response the current response* @return*/@Overridepublic Object beforeBodyWrite(Object body,MethodParameter returnType,MediaType selectedContentType,Class<? extends HttpMessageConverter<?>> selectedConverterType,ServerHttpRequest request,ServerHttpResponse response) {if (returnType.getParameterType().equals(String.class)){// 如果是String类需要特殊处理ObjectMapper objectMapper = new ObjectMapper();try {// 设置响应数据格式为jsonresponse.getHeaders().add("content-type","application/json;charset=UTF-8");return objectMapper.writeValueAsString(Result.success(body));} catch (JsonProcessingException e) {throw new RuntimeException(e);}}return Result.success(body);}}
工程结构
用户controller
package com.zhao.wechat.rest;import com.zhao.wechat.domain.UserInfo;
import com.zhao.wechat.service.UserInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.*;import java.util.List;/*** 用户信息管理视图层*/
@RestController
@RequestMapping("/userInfo")
@Api(tags = "用户信息管理")
public class UserInfoRest {@Autowiredprivate UserInfoService userInfoService;/*** 分页获取所有的用户* @return*/@ApiOperation(value = "分页获取所有的用户")@PostMapping("/queryPage")public Page<UserInfo> queryUserPage(@PageableDefault Pageable pageable){Page<UserInfo> userInfos = userInfoService.queryUserPage(pageable.getPageNumber(), pageable.getPageSize());return userInfos;}/*** 添加或者修改用户*/@ApiOperation(value = "添加或者修改用户")@PostMapping("/saveOrUpdate")public void saveOrUpdate(@RequestBody UserInfo userInfo){userInfoService.saveOrUpdate(userInfo);}/*** 删除用户*/@ApiOperation(value = "删除用户")@DeleteMapping("/delete")public void deleteUserById(@RequestParam("id") Long id){userInfoService.deleteUserById(id);}}
调用第三方接口
package com.zhao.wechat.remote;import com.zhao.wechat.remote.param.TianXinParam;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.SpringQueryMap;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;/*** 第三方接口天行数据*/
@FeignClient(value = "TianDataRemoteClient",url = "${tianxin.server}")
public interface TianDataRemoteClient {/*** 获取彩虹屁*/@GetMapping(value = "/caihongpi/index",consumes = {MediaType.APPLICATION_JSON_VALUE},produces = {MediaType.APPLICATION_JSON_VALUE})String queryRainbow(@SpringQueryMap TianXinParam tianXinParam);/*** 获取优美的句子*/@GetMapping(value = "/ensentence/index",consumes = {MediaType.APPLICATION_JSON_VALUE},produces = {MediaType.APPLICATION_JSON_VALUE})String queryEnsentence(@SpringQueryMap TianXinParam tianXinParam);}
推送微信数据
package com.zhao.wechat.service;import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.zhao.wechat.config.WechatConfig;import com.zhao.wechat.config.WechatTemplate;
import com.zhao.wechat.config.WechatTemplateList;
import com.zhao.wechat.domain.*;
import com.zhao.wechat.remote.BaiduWeatherRemoteClient;
import com.zhao.wechat.remote.TianDataRemoteClient;
import com.zhao.wechat.remote.param.BaiduWeatherParam;
import com.zhao.wechat.remote.param.TianXinParam;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;@Slf4j
@Service
public class PushDailyWechatImpl implements PushDailyWechat{@Autowiredprivate UserInfoService userInfoService;@Autowiredprivate BaiduWeatherRemoteClient baiduWeatherRemoteClient;@Autowiredprivate TianDataRemoteClient tianDataRemoteClient;/** 微信配置类 **/@Autowiredprivate WechatConfig wechatConfig;/** 模板列表**/@Autowiredprivate WechatTemplateList wechatTemplateList;/** ak **/@Value("${baidu.ak}")private String ak;/** key **/@Value("${tianxin.key}")private String key;/*** 给不同的用户推送消息*/@Overridepublic void pushWechat() throws WxErrorException {// 获取用户列表List<UserInfo> userInfoList = userInfoService.listUserInfo();if (!CollectionUtils.isEmpty(userInfoList)){// 根据用户的type类型和模板type进行匹配for (UserInfo userInfo : userInfoList) {for (WechatTemplate template : wechatTemplateList.getTemplatelist()) {if (userInfo.getType().equals(template.getType())){this.wechatData(userInfo.getWechatId(), template.getTemplateId(),userInfo);}}}}}/*** 封装微信数据* @param wechatId* @param templateId*/private void wechatData(String wechatId,String templateId,UserInfo userInfo) throws WxErrorException {// 创建配置信息WxMpInMemoryConfigStorage wxStorage = new WxMpInMemoryConfigStorage();wxStorage.setAppId(wechatConfig.getAppId());wxStorage.setSecret(wechatConfig.getAppSecret());WxMpService wxMpService = new WxMpServiceImpl();wxMpService.setWxMpConfigStorage(wxStorage);// 创建模板信息WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder().toUser(wechatId).templateId(templateId).build();// 获取天气预报信息BaiduWeatherParam baiduWeatherParam = BaiduWeatherParam.builder().district_id(userInfo.getDistrictId()).data_type("all").ak(this.ak).build();String queryWeather = baiduWeatherRemoteClient.queryWeather(baiduWeatherParam);log.info("查询的百度天气信息为:{}",queryWeather);BaiduNowWeather baiduNowWeather = ApiResponse.parseBaiduNowData(queryWeather, BaiduNowWeather.class);List<BaiduForecastsWeather> baiduForecastsWeatherList = ApiResponse.parseBaiduForecastsData(queryWeather, BaiduForecastsWeather.class);log.info("baiduNowWeather:{},baiduForecastsWeather:{}",baiduNowWeather,baiduForecastsWeatherList);// 获取彩虹屁TianXinParam tianXinParam = TianXinParam.builder().key(this.key).build();String queryRainbow = tianDataRemoteClient.queryRainbow(tianXinParam);List<TianRainbow> rainbowList = ApiResponse.parseTianData(queryRainbow, TianRainbow.class);// 获取每日一句String queryEnsentence = tianDataRemoteClient.queryEnsentence(tianXinParam);List<TianEnsentence> tianEnsentenceList = ApiResponse.parseTianData(queryEnsentence, TianEnsentence.class);// 封装模板数据templateMessage.addData(new WxMpTemplateData("now", this.pareDateNow(baiduForecastsWeatherList.get(0)),"#FFB6C1"));templateMessage.addData(new WxMpTemplateData("city",userInfo.getCity(),"#B95EA6"));templateMessage.addData(new WxMpTemplateData("text",baiduNowWeather.getText(),"#173177"));templateMessage.addData(new WxMpTemplateData("high",baiduForecastsWeatherList.get(0).getHigh(),"#87cefa"));templateMessage.addData(new WxMpTemplateData("low",baiduForecastsWeatherList.get(0).getLow(),"#FF6347"));templateMessage.addData(new WxMpTemplateData("scq_day",this.calScqDate(userInfo),"#FF1493"));templateMessage.addData(new WxMpTemplateData("bir_day",this.calBirData(userInfo),"#FF00FF" ));templateMessage.addData(new WxMpTemplateData("daily_english_cn",rainbowList.get(0).getContent(),"#800080"));templateMessage.addData(new WxMpTemplateData("daily_english_en",tianEnsentenceList.get(0).getEn(),"#FFA500"));log.info("发送的消息为:{}", JSON.toJSONString(templateMessage));wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);}/*** 计算想认识/想恋日期* @return*/private String calScqDate(UserInfo userInfo){// 获取第一次想认识的时间if (Objects.nonNull(userInfo)){Date scqTime = userInfo.getScqTime();// 计算时间差long between = DateUtil.between(scqTime, DateUtil.date(), DateUnit.DAY);return String.valueOf(between);}return "";}/*** 计算生日* @param userInfo* @return*/private String calBirData(UserInfo userInfo){// 获取用户的出生日期if (Objects.nonNull(userInfo)){Date birTime = userInfo.getBirTime();// 今日日期Calendar today = Calendar.getInstance();// 出生日期Calendar birthDay = Calendar.getInstance();// 设置生日birthDay.setTime(birTime);// 修改为本年int bir;birthDay.set(Calendar.YEAR,today.get(Calendar.YEAR));if (birthDay.get(Calendar.DAY_OF_YEAR) < today.get(Calendar.DAY_OF_YEAR)){// 生日已经过了,计算明年的bir = today.getActualMaximum(Calendar.DAY_OF_YEAR) - today.get(Calendar.DAY_OF_YEAR);bir += birthDay.get(Calendar.DAY_OF_YEAR);} else {// 生日还没过bir = birthDay.get(Calendar.DAY_OF_YEAR) - today.get(Calendar.DAY_OF_YEAR);}return String.valueOf(bir);}return "";}/*** 拼接今日时间* @return*/private String pareDateNow(BaiduForecastsWeather baiduForecastsWeather){// 获取当前日期String now = DateUtil.format(DateUtil.date(), DatePattern.CHINESE_DATE_PATTERN);// 获取星期几String week = baiduForecastsWeather.getWeek();return now+" "+week;}
}
定时任务
package com.zhao.wechat.job;import com.zhao.wechat.service.PushDailyWechat;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;/*** 推送消息到用户定时任务*/
@Component
public class PushWechatJob {@Autowiredprivate PushDailyWechat pushDailyWechat;/*** 每天早上7点推送到微信* @throws WxErrorException*/@Scheduled(cron = "0 30 7 1/1 * ? ")void doJob() throws WxErrorException {pushDailyWechat.pushWechat();}
}
效果
推送到微信
使用springboot每日推送早安问候语到用户微信相关推荐
- 使用springboot每日推送早安问候语到用户微信【部署篇】
上一篇介绍文章 上一篇介绍文章 https://blog.csdn.net/weixin_45206218/article/details/127872136 代码仓库 代码仓库 https://gi ...
- bars 除障句完整_精选每日一句早安问候语语录49句
精选每日一句早安问候语语录49句 任何事情都是这样一个过程,决定去做了,就着手去做,一旦找到了舒适区,你就会乐在其中,或许就发现:"喜欢比努力更重要."乐在其中地去坚持一件事,总好 ...
- 公众号推送早安问候以及天气预报(JAVA)
公众号推送早安问候以及天气预报(JAVA) ① 概述 功能点 每天早上可以给指定的微信用户推送消息,经过公众号 可以使用第三方接口丰富推送的消息内容 百度天气api:添加天气信息推送 天行数据api: ...
- 用公众号给女朋友推送早安问候(恋爱值♥♥♥♥♥)
前言 最近,女朋友给我推了一个抖音视频,讲述的是一个女孩子收到了她对象的早安问候,里面文字花花绿绿,问候词都快羞红了我的脸,不过,看的出来她很喜欢.好吧,我懂了.于是,不太会公众号开发的我去B站学习了 ...
- 女神节来了,快给那个Ta做个公众号推送早安问候及天气预报,可自动定时推送哦~
女神节到了,程序员必备撩妹怎会没有方法?微信自动发送问候语以及天气预报,快给那个Ta做一个吧! 通用设置 注意:本小节所有要小本本记下的内容都要填写到配置文件config.txt里的哦~ ▲ *con ...
- 图片的宽铺满全屏 微信小程序_2020冬至快乐图片!,图片祝福贺卡,朋友圈冬至早安问候语动态图片微信小程序...
朋友你好,2020冬至快乐! 冬至的雪,美丽着脸庞,飘逸冬的梦想:冬至的汤,沸腾着喜悦,感受夏的热浪!一年中最冷的时候到了,祝你:快乐如雪,温暖如汤!冬至快乐! 冬至吃饺子,一个饺子一颗心.吃韭菜馅饺 ...
- 企业微信每日给女友推送早安,5分钟快速部署,腾讯云部署版本,每日定时发送,天气,鸡汤,纪念日等信息,可自定义通知提醒名称,聊天界面可置顶,内容可查图片。
企业微信每日给女朋友推送早安,5分钟快速部署,每日定时发送,天气,鸡汤,纪念日等信息,可自定义通知提醒名称,聊天界面可置顶,内容可查图片. 先看效果 直接开搞 准备工作 1.企业id 2.企业应用se ...
- 1.8 微信推送早安及天气预报信息(Springboot框架)(二)
微信推送早安及天气预报信息(搭建框架和代码完善) 目录 一.搭建框架 1. 环境准备 2. 搭建Springboot框架 二.获取代码并完善 1. pom.xml 2. application.yml ...
- 1.7 微信推送早安及天气预报信息(Springboot框架)(一)
微信推送早安及天气预报信息(开发前期准备) 目录 一.申请天行数据API接口 1. 注册 2. 登录 3. 验证邮箱 4. [申请接口] 5. [我的密钥KEY] 二.申请实况天气API接口 1. 注 ...
最新文章
- Firefox无法加载12306自家证书
- 光模块价格由带宽还是距离决定_100G QSFP28 CWDM4光模块介绍及应用
- 关于图片延迟加载的解决方案(针对移动端)
- 第二季1:图像基础知识
- QT5 获取窗口、系统屏幕大小尺寸信息,Qt 获取控件位置坐标,屏幕坐标,相对父窗体坐标
- python库_python使用ctypes库调用DLL动态链接库_python
- BZOJ1433[ZJOI2009]假期的宿舍——二分图最大匹配
- 下一个阶段(用C++重写Lucene的计划)
- python一行输出_#python版一行内容分行输出
- 耳机使用说明书 jbl ua_怎么挑选一款适合自己的蓝牙耳机?看看这篇文章!
- 项目管理系统与项目管理信息系统与配置管理系统与变更控制系统的区别
- my top visited webs
- 移动Ad Hoc网络路由协议汇总
- 进入mariadb_MariaDB基础操作
- C++(4)——对称/旋转
- PMP考纲解读 |【人】任务3—支持团队绩效(二)
- Python3网络爬虫教程7——SSL数字证书
- 手机sd卡恢复工具android版,手机内存卡文件恢复工具(SD卡数据恢复助手)V1.5 正式版...
- 大陆居民如何在香港银行开户并汇款?
- 十进制进制法_关于二进制、十进制、八进制、十六进制数据转换计算方法详细总结...
热门文章
- ContentProvider导致App闪退问题分析
- python xlwt写入excel_python xlwt模块生成excel文件并写入数据 xlrd读取数据
- docker push 镜像 An image does not exist locally with the tag
- android view的绘制原理,SurfaceView 原理
- 屡试屡爽的无桌面linux安装oracle操作流程
- 打开svn时候出现R6034
- COleVariant
- No bean named ‘transactionManager‘ available: No matching TransactionManager bean found for qualifie
- CRM项目 - 心得
- Flink教程(13) Keyed State状态管理之ValueState的使用 温差报警