0


使用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"?><projectxmlns="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: 微信appid
    appSecret: 微信appSecret
  # 模板消息集合
  templatelist:
    - type: 1
      templateId: 微信模板id
    - type: 2
      templateId: 微信模板id
    - type: 3
      templateId: 微信模板id
# 百度天气配置
baidu:
  server: https://api.map.baidu.com
  ak: 百度数据的ak
# 天行数据
tianxin:
  server: http://api.tianapi.com
  key: 天行数据的key
spring:
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://ip:3306/库名?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: 564929
    hikari:
      minimum-idle: 5
      # 空闲连接存活最大时间,默认600000(10分钟)
      idle-timeout: 180000
      # 连接池最大连接数,默认是10
      maximum-pool-size: 10
      # 此属性控制从池返回的连接的默认自动提交行为,默认值:true
      auto-commit: true
      # 连接池名称
      pool-name: MyHikariCP
      # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
      max-lifetime: 1800000
      # 数据库连接超时时间,默认30秒,即30000
      connection-timeout: 30000
      connection-test-query: SELECT 1
  jpa:
    show-sql: true # 默认false,在日志里显示执行的sql语句
    database: mysql
    database-platform: org.hibernate.dialect.MySQL5Dialect
    hibernate:
      ddl-auto: update #指定为update,每次启动项目检测表结构有变化的时候会新增字段,表不存在时会 新建,如果指定create,则每次启动项目都会清空数据并删除表,再新建
      naming:
        #指定jpa的自动表生成策略,驼峰自动映射为下划线格式7
        implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
        #physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
# 日志
#logging:
#  config: classpath:logback-spring-dev.xml

统一数据封装

packagecom.zhao.wechat.advice;importcom.fasterxml.jackson.core.JsonProcessingException;importcom.fasterxml.jackson.databind.ObjectMapper;importcom.zhao.wechat.common.Result;importlombok.extern.slf4j.Slf4j;importorg.springframework.core.MethodParameter;importorg.springframework.http.MediaType;importorg.springframework.http.converter.HttpMessageConverter;importorg.springframework.http.server.ServerHttpRequest;importorg.springframework.http.server.ServerHttpResponse;importorg.springframework.web.bind.annotation.RestControllerAdvice;importorg.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;/**
 * 对前端响应结果统一封装
 */@Slf4j@RestControllerAdvice(basePackages ={"com.zhao.wechat.rest"})publicclassApiResponseAdviceimplementsResponseBodyAdvice<Object>{/**
     * 打印统一请求响应规范
     */ApiResponseAdvice(){
        log.info("启动请求统一响应规范... ...");}/**
     * 判断是否需要对返回值进行封装
     * @param returnType the return type
     * @param converterType the selected converter type
     * @return
     */@Overridepublicbooleansupports(MethodParameter returnType,Class<?extendsHttpMessageConverter<?>> converterType){// 如果返回的结果是Result.class类型就不用封装if(returnType.getParameterType().equals(Result.class)){returnfalse;}returntrue;}/**
     * 对返回前端的值统一封装
     * @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
     */@OverridepublicObjectbeforeBodyWrite(Object body,MethodParameter returnType,MediaType selectedContentType,Class<?extendsHttpMessageConverter<?>> selectedConverterType,ServerHttpRequest request,ServerHttpResponse response){if(returnType.getParameterType().equals(String.class)){// 如果是String类需要特殊处理ObjectMapper objectMapper =newObjectMapper();try{// 设置响应数据格式为json
             response.getHeaders().add("content-type","application/json;charset=UTF-8");return objectMapper.writeValueAsString(Result.success(body));}catch(JsonProcessingException e){thrownewRuntimeException(e);}}returnResult.success(body);}}

工程结构

在这里插入图片描述

用户controller

packagecom.zhao.wechat.rest;importcom.zhao.wechat.domain.UserInfo;importcom.zhao.wechat.service.UserInfoService;importio.swagger.annotations.Api;importio.swagger.annotations.ApiOperation;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.data.domain.Page;importorg.springframework.data.domain.Pageable;importorg.springframework.data.web.PageableDefault;importorg.springframework.web.bind.annotation.*;importjava.util.List;/**
 * 用户信息管理视图层
 */@RestController@RequestMapping("/userInfo")@Api(tags ="用户信息管理")publicclassUserInfoRest{@AutowiredprivateUserInfoService userInfoService;/**
     * 分页获取所有的用户
     * @return
     */@ApiOperation(value ="分页获取所有的用户")@PostMapping("/queryPage")publicPage<UserInfo>queryUserPage(@PageableDefaultPageable pageable){Page<UserInfo> userInfos = userInfoService.queryUserPage(pageable.getPageNumber(), pageable.getPageSize());return userInfos;}/**
     * 添加或者修改用户
     */@ApiOperation(value ="添加或者修改用户")@PostMapping("/saveOrUpdate")publicvoidsaveOrUpdate(@RequestBodyUserInfo userInfo){
        userInfoService.saveOrUpdate(userInfo);}/**
     * 删除用户
     */@ApiOperation(value ="删除用户")@DeleteMapping("/delete")publicvoiddeleteUserById(@RequestParam("id")Long id){
        userInfoService.deleteUserById(id);}}

调用第三方接口

packagecom.zhao.wechat.remote;importcom.zhao.wechat.remote.param.TianXinParam;importorg.springframework.cloud.openfeign.FeignClient;importorg.springframework.cloud.openfeign.SpringQueryMap;importorg.springframework.http.MediaType;importorg.springframework.web.bind.annotation.GetMapping;/**
 * 第三方接口天行数据
 */@FeignClient(value ="TianDataRemoteClient",url ="${tianxin.server}")publicinterfaceTianDataRemoteClient{/**
     * 获取彩虹屁
     */@GetMapping(value ="/caihongpi/index",
            consumes ={MediaType.APPLICATION_JSON_VALUE},
            produces ={MediaType.APPLICATION_JSON_VALUE})StringqueryRainbow(@SpringQueryMapTianXinParam tianXinParam);/**
     * 获取优美的句子
     */@GetMapping(value ="/ensentence/index",
            consumes ={MediaType.APPLICATION_JSON_VALUE},
            produces ={MediaType.APPLICATION_JSON_VALUE})StringqueryEnsentence(@SpringQueryMapTianXinParam tianXinParam);}

推送微信数据

packagecom.zhao.wechat.service;importcn.hutool.core.date.DatePattern;importcn.hutool.core.date.DateUnit;importcn.hutool.core.date.DateUtil;importcn.hutool.core.util.StrUtil;importcom.alibaba.fastjson2.JSON;importcom.zhao.wechat.config.WechatConfig;importcom.zhao.wechat.config.WechatTemplate;importcom.zhao.wechat.config.WechatTemplateList;importcom.zhao.wechat.domain.*;importcom.zhao.wechat.remote.BaiduWeatherRemoteClient;importcom.zhao.wechat.remote.TianDataRemoteClient;importcom.zhao.wechat.remote.param.BaiduWeatherParam;importcom.zhao.wechat.remote.param.TianXinParam;importlombok.extern.slf4j.Slf4j;importme.chanjar.weixin.common.error.WxErrorException;importme.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;importme.chanjar.weixin.mp.api.WxMpService;importme.chanjar.weixin.mp.api.impl.WxMpServiceImpl;importme.chanjar.weixin.mp.bean.template.WxMpTemplateData;importme.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.stereotype.Service;importorg.springframework.util.CollectionUtils;importjava.time.format.DateTimeFormatter;importjava.util.Calendar;importjava.util.Date;importjava.util.List;importjava.util.Objects;@Slf4j@ServicepublicclassPushDailyWechatImplimplementsPushDailyWechat{@AutowiredprivateUserInfoService userInfoService;@AutowiredprivateBaiduWeatherRemoteClient baiduWeatherRemoteClient;@AutowiredprivateTianDataRemoteClient tianDataRemoteClient;/** 微信配置类 **/@AutowiredprivateWechatConfig wechatConfig;/** 模板列表**/@AutowiredprivateWechatTemplateList wechatTemplateList;/** ak **/@Value("${baidu.ak}")privateString ak;/** key **/@Value("${tianxin.key}")privateString key;/**
     * 给不同的用户推送消息
     */@OverridepublicvoidpushWechat()throwsWxErrorException{// 获取用户列表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
     */privatevoidwechatData(String wechatId,String templateId,UserInfo userInfo)throwsWxErrorException{// 创建配置信息WxMpInMemoryConfigStorage wxStorage =newWxMpInMemoryConfigStorage();
        wxStorage.setAppId(wechatConfig.getAppId());
        wxStorage.setSecret(wechatConfig.getAppSecret());WxMpService wxMpService =newWxMpServiceImpl();
        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(newWxMpTemplateData("now",this.pareDateNow(baiduForecastsWeatherList.get(0)),"#FFB6C1"));
        templateMessage.addData(newWxMpTemplateData("city",userInfo.getCity(),"#B95EA6"));
        templateMessage.addData(newWxMpTemplateData("text",baiduNowWeather.getText(),"#173177"));
        templateMessage.addData(newWxMpTemplateData("high",baiduForecastsWeatherList.get(0).getHigh(),"#87cefa"));
        templateMessage.addData(newWxMpTemplateData("low",baiduForecastsWeatherList.get(0).getLow(),"#FF6347"));
        templateMessage.addData(newWxMpTemplateData("scq_day",this.calScqDate(userInfo),"#FF1493"));
        templateMessage.addData(newWxMpTemplateData("bir_day",this.calBirData(userInfo),"#FF00FF"));
        templateMessage.addData(newWxMpTemplateData("daily_english_cn",rainbowList.get(0).getContent(),"#800080"));
        templateMessage.addData(newWxMpTemplateData("daily_english_en",tianEnsentenceList.get(0).getEn(),"#FFA500"));

        log.info("发送的消息为:{}",JSON.toJSONString(templateMessage));
        wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);}/**
     * 计算想认识/想恋日期
     * @return
     */privateStringcalScqDate(UserInfo userInfo){// 获取第一次想认识的时间if(Objects.nonNull(userInfo)){Date scqTime = userInfo.getScqTime();// 计算时间差long between =DateUtil.between(scqTime,DateUtil.date(),DateUnit.DAY);returnString.valueOf(between);}return"";}/**
     * 计算生日
     * @param userInfo
     * @return
     */privateStringcalBirData(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);}returnString.valueOf(bir);}return"";}/**
     * 拼接今日时间
     * @return
     */privateStringpareDateNow(BaiduForecastsWeather baiduForecastsWeather){// 获取当前日期String now =DateUtil.format(DateUtil.date(),DatePattern.CHINESE_DATE_PATTERN);// 获取星期几String week = baiduForecastsWeather.getWeek();return now+" "+week;}}

定时任务

packagecom.zhao.wechat.job;importcom.zhao.wechat.service.PushDailyWechat;importme.chanjar.weixin.common.error.WxErrorException;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.scheduling.annotation.Scheduled;importorg.springframework.stereotype.Component;/**
 * 推送消息到用户定时任务
 */@ComponentpublicclassPushWechatJob{@AutowiredprivatePushDailyWechat pushDailyWechat;/**
     * 每天早上7点推送到微信
     * @throws WxErrorException
     */@Scheduled(cron ="0 30 7 1/1 * ? ")voiddoJob()throwsWxErrorException{
        pushDailyWechat.pushWechat();}}

效果

在这里插入图片描述

推送到微信

在这里插入图片描述


本文转载自: https://blog.csdn.net/weixin_45206218/article/details/127872136
版权归原作者 stevezhao6 所有, 如有侵权,请联系我们删除。

“使用springboot每日推送早安问候语到用户微信”的评论:

还没有评论