当前位置:   article > 正文

【小项目】微信定时推送天气预报Github项目使用及原理介绍-包含cron、天气预报、常用api...

github微信推送

一、资料链接

1、github地址

https://github.com/qq1534774766/wx-push

2、教程地址

https://blog.csdn.net/qq15347747/article/details/126521774

3、易客云API(自动发送天气)

https://yikeapi.com/account/index

4、apispace-各种接口(名人名言)

https://www.apispace.com/console/api?orgId=6356

5、微信公众平台

https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index

二、准备工作

(一)进入接口测试页面

1、找到微信公众平台

2、进入开发者工具

3、进入公众平台测试帐号

4、拉到最下面

微信扫码关注

5、记录下述信息

(二)获取天气预报接口地址

1、进入易客云API(自动发送天气)

https://yikeapi.com/account/index

2、注册登录

3、复制参数appid和appsecret的值

4、记录下述信息

(三)获取(名言警句)地址

1、进入apispace-各种接口

https://www.apispace.com/console/api?orgId=6356

2、注册登录

3、购买名言警句

4、进入我的api,点击测试

5、复制token地址

6、记录下述信息

三、开发部署

1、下载项目

git下载:https://github.com/qq1534774766/wx-push.git

2、填写上述参数(application.yml)

3、配置定时

填写cron表达式@Scheduled(cron = "0 30 7 ? * *")

实现方式:import org.springframework.scheduling.annotation.Scheduled;

4、启动项目

5、测试

修改天气预报城市:localhost:8081

测试发送消息:localhost:8081/send

6、打包上传服务器

nohup java -jar wx.jar >wx.txt &

四、优化

(一)cron表达式配置及含义

1、启动类加注解

@EnableScheduling

2、几分钟执行一次

  1. /**
  2. * 固定频率执行。fixedDelay的单位是ms
  3. */
  4. @Scheduled(fixedDelay = 1000)
  5. public void remindTask2() throws InterruptedException {
  6. log.info("每隔1s执行一次 当前线程名称{} 当前执行次数{}", Thread.currentThread().getName(), task1Number.incrementAndGet());
  7. }

3、cron表达式配置

5秒执行一次

  1. @Scheduled(cron = "*/5 * * * * ? ")
  2. public void remindTask() throws InterruptedException {
  3. log.info("每隔5秒执行一次, 当前线程名称{} 当前执行次数{}", Thread.currentThread().getName(), taskNumber.incrementAndGet());
  4. }

ps:?的含义是

“?”字符仅被用于天(月)和天(星期)两个子表达式,表示不指定值 当2个子表达式其中之一被指定了值以后,为了避免冲突,需要将另一个子表达式的值设为“?”

项目使用

  1. @Scheduled(cron = "0 30 7 ? * *")
  2. @RequestMapping("/send")
  3. public String send() {
  4. try {
  5. return sendService.sendWeChatMsg();
  6. } catch (Exception e) {
  7. e.printStackTrace();
  8. }
  9. JSONObject json = new JSONObject();
  10. json.put("msg", "信息推送失败");
  11. return json.toJSONString();
  12. }

corn从左到右(用空格隔开):秒 分 小时 月份中的日期 月份 星期中的日期 年份

DayofMonth和DayofWeek会相互影响

校验:https://www.bejson.com/othertools/cronvalidate/

日期和星期相互影响,必须配置一个?【?表示不指定周几或每月几号,因为二者相互影响】

配置哪个含义相同

(二)配置名言外的其他api(apispace)

找到名言警句的配置地址

配置其他api

1、示例文档地址

https://www.apispace.com/console/api?orgId=6356

2、示例代码

  1. OkHttpClient client = new OkHttpClient().newBuilder().build();
  2. MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
  3. RequestBody body = RequestBody.create(mediaType, "titleID=1");
  4. Request request = new Request.Builder()
  5. .url("https://eolink.o.apispace.com/myjj/common/aphorism/getAphorismList")
  6. .method("POST",body)
  7. .addHeader("X-APISpace-Token","s2qvfzkmuzb9vq7pvw8tnll882rhrarl")
  8. .addHeader("Authorization-Type","apikey")
  9. .addHeader("Content-Type","application/x-www-form-urlencoded")
  10. .build();
  11. Response response = client.newCall(request).execute();

3、实际代码

ProverbServiceImpl

  1. @Override
  2. public String getOneNormalProverb() {
  3. String proverb = null;
  4. try {
  5. OkHttpClient client = new OkHttpClient().newBuilder().build();
  6. MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
  7. RequestBody body = RequestBody.create(mediaType, "titleID="+new Random().nextInt(9));
  8. Request request = new Request.Builder()
  9. .url("https://eolink.o.apispace.com/myjj/common/aphorism/getAphorismList")
  10. .method("POST", body)
  11. .addHeader("X-APISpace-Token", configConstant.getToken())
  12. .addHeader("Authorization-Type", "apikey")
  13. .addHeader("Content-Type", "")
  14. .build();Response response = client.newCall(request).execute();
  15. JSONObject jsonObject = JSONObject.parseObject(response.body().string());
  16. //取出全部句子
  17. JSONArray allProverb = JSONObject.parseArray((String) jsonObject.getJSONArray("result").getJSONObject(0).get("words"));
  18. //随机取出一条句子
  19. String s = (String) allProverb.get(new Random().nextInt(allProverb.size()));
  20. //去除无关元素
  21. proverb = s.replaceAll("^.*、", "");
  22. } catch (IOException e) {
  23. throw new RuntimeException(e);
  24. }
  25. return proverb;
  26. }

通过有道翻译为英文

  1. @Override
  2. public String translateToEnglish(String sentence) {
  3. String result = null;
  4. try {
  5. OkHttpClient client = new OkHttpClient().newBuilder().build();
  6. Request request = new Request.Builder()
  7. .url("https://fanyi.youdao.com/translate?&doctype=json&type=AUTO&i="+sentence)
  8. .get()
  9. .addHeader("Content-Type","")
  10. .build();
  11. Response response = client.newCall(request).execute();
  12. result = response.body().string();
  13. //解析
  14. JSONObject jsonObject = JSONObject.parseObject(result);
  15. result = jsonObject.getJSONArray("translateResult").getJSONArray(0).getJSONObject(0).getString("tgt");
  16. }catch (Exception e) {
  17. e.printStackTrace();
  18. }
  19. return result;
  20. }

(三)配置天气预报的原理(易客云)

1、得到当日天气

  1. public JSONObject getWeatherByCity() {
  2. String result = null;
  3. try {
  4. OkHttpClient client = new OkHttpClient.Builder().build();
  5. HttpUrl url = new HttpUrl.Builder()
  6. .scheme("https")
  7. .host("www.yiketianqi.com")
  8. .addPathSegments("free/day")
  9. .addQueryParameter("appid", configConstant.getWeatherAppId())
  10. .addQueryParameter("appsecret", configConstant.getWeatherAppSecret())
  11. .addQueryParameter("city", configConstant.getCity())
  12. .addQueryParameter("unescape", "1")
  13. .build();
  14. Request request = new Request.Builder()
  15. .url(url)
  16. .get()
  17. .build();
  18. Response re = client.newCall(request).execute();
  19. result = re.body().string();
  20. } catch (IOException e) {
  21. e.printStackTrace();
  22. }
  23. return JSONObject.parseObject(result);
  24. }

2、得到三日天气

  1. public Map<String, String> getTheNextThreeDaysWeather() {
  2. Map<String, String> map = null;
  3. try {
  4. OkHttpClient client = new OkHttpClient.Builder().build();
  5. HttpUrl url = new HttpUrl.Builder()
  6. .scheme("https")
  7. .host("yiketianqi.com")
  8. .addPathSegments("free/week")
  9. .addQueryParameter("appid", configConstant.getWeatherAppId())
  10. .addQueryParameter("appsecret", configConstant.getWeatherAppSecret())
  11. .addQueryParameter("city", configConstant.getCity())
  12. .build();
  13. Request request = new Request.Builder()
  14. .url(url)
  15. .get()
  16. .build();
  17. Response response = client.newCall(request).execute();
  18. String responseResult = response.body().string();
  19. if (!StringUtils.hasText(responseResult)) {
  20. logger.error("获取三天天气失败,检查配置文件");
  21. throw new RuntimeException("获取三天天气失败,检查配置文件");
  22. }
  23. logger.info(responseResult);
  24. ZoneId zoneId = ZoneId.of("Asia/Shanghai");
  25. LocalDate now = LocalDate.now(zoneId);
  26. //封装今天,明天,后天的时间
  27. /**
  28. * 原因分析:从天气api获取到未来的天气的日期是 01 02 03 的两位数。
  29. * 而Java中的LocalDate的日期,是一位数的 1 2 3
  30. * 因为一开始用是String类型比较,所以011,最后导致异常。
  31. */
  32. Map<Integer, String> daySet = new HashMap<>();
  33. daySet.put(now.getDayOfMonth(), "今"); // 用now,就不会报错了,1 2 3
  34. daySet.put(now.plusDays(1L).getDayOfMonth(), "明");
  35. daySet.put(now.plusDays(2L).getDayOfMonth(), "后");
  36. //过滤,提取结果
  37. JSONObject jsonObject = JSONObject.parseObject(responseResult);
  38. if (jsonObject.containsKey("errmsg")) {
  39. logger.error(jsonObject.getString("errmsg"));
  40. throw new IllegalArgumentException(jsonObject.getString("errmsg"));
  41. }
  42. map = jsonObject.getJSONArray("data").stream()
  43. .peek(o -> {
  44. String date = getStringFromJson(o, "date").substring(8);
  45. ((JSONObject) o).put("date", date);
  46. })
  47. .filter(o -> daySet.containsKey(getIntegerFromJson(o, "date")))
  48. .collect(Collectors.toMap(
  49. key -> daySet.get(getIntegerFromJson(key, "date")),
  50. value -> getStringFromJson(value, "wea")));
  51. } catch (IOException e) {
  52. e.printStackTrace();
  53. throw new RuntimeException("获取失败");
  54. }
  55. return map;
  56. }

(四)发送消息

1、封装各项请求的内容

  1. if (configConstant.isEnableDaily() && StringUtils.hasText(configConstant.getToken())) {
  2. //名言警句,中文
  3. String noteZh = null;
  4. try {
  5. noteZh = proverbService.getOneNormalProverb();
  6. JSONObject note_Zh = JsonObjectUtil.packJsonObject(noteZh, "#879191");
  7. resultMap.put("note_Zh", note_Zh);
  8. logger.info("note_Zh:{}", note_Zh);
  9. } catch (Exception e) {
  10. logger.info("名言警句获取失败,检查ApiSpace的token是否正确?套餐是否过期?");
  11. }
  12. //名言警句,英文
  13. try {
  14. JSONObject note_En = JsonObjectUtil.packJsonObject(proverbService.translateToEnglish(noteZh), "#879191");
  15. resultMap.put("note_En", note_En);
  16. logger.info("note_En:{}", note_En);
  17. } catch (Exception e) {
  18. logger.info("名言警句翻译失败,网易云翻译接口无法使用");
  19. }
  20. }
  21. //封装数据并发送
  22. sendMessage(accessToken, errorList, resultMap, opedId);

2、发送到微信token

  1. private void sendMessage(String accessToken, List<JSONObject> errorList, HashMap<String, Object> resultMap, String opedId) {
  2. JSONObject templateMsg = new JSONObject(new LinkedHashMap<>());
  3. templateMsg.put("touser", opedId);
  4. templateMsg.put("template_id", configConstant.getTemplateId());
  5. templateMsg.put("data", new JSONObject(resultMap));
  6. String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken;
  7. String sendPost = HttpUtil.sendPost(url, templateMsg.toJSONString());
  8. JSONObject WeChatMsgResult = JSONObject.parseObject(sendPost);
  9. if (!"0".equals(WeChatMsgResult.getString("errcode"))) {
  10. JSONObject error = new JSONObject();
  11. error.put("openid", opedId);
  12. error.put("errorMessage", WeChatMsgResult.getString("errmsg"));
  13. errorList.add(error);
  14. }
  15. }

五、技术总结

1、Scheduleh注解定时调任务

2、微信token发送指定消息

3、调用接口得到数据(天气预报和各种api)

4、姓名如何在方法头上标注

5、代码结构

6、配置参数调用-通过value和自动注入

configConstant.getWeatherAppId()

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号