xiaowang 1 mesiac pred
commit
6654cf806b

+ 33 - 0
.gitignore

@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/

+ 209 - 0
logs/getWeather.log

@@ -0,0 +1,209 @@
+2025-03-11 11:10:57.293 [main] INFO  com.example.getweather.GetWeatherApplication - Starting GetWeatherApplication using Java 1.8.0_372 on xiaowang.local with PID 15684 (/Users/xiaowang/IdeaProjects/getWeather/target/classes started by xiaowang in /Users/xiaowang/IdeaProjects/getWeather)
+2025-03-11 11:10:57.296 [main] INFO  com.example.getweather.GetWeatherApplication - No active profile set, falling back to 1 default profile: "default"
+2025-03-11 11:10:57.607 [main] INFO  com.example.getweather.GetWeatherApplication - Started GetWeatherApplication in 0.503 seconds (JVM running for 0.845)
+2025-03-11 11:11:13.940 [main] INFO  com.example.getweather.GetWeatherApplication - Starting GetWeatherApplication using Java 1.8.0_372 on xiaowang.local with PID 15705 (/Users/xiaowang/IdeaProjects/getWeather/target/classes started by xiaowang in /Users/xiaowang/IdeaProjects/getWeather)
+2025-03-11 11:11:13.941 [main] INFO  com.example.getweather.GetWeatherApplication - No active profile set, falling back to 1 default profile: "default"
+2025-03-11 11:11:14.233 [main] INFO  com.example.getweather.GetWeatherApplication - Started GetWeatherApplication in 0.468 seconds (JVM running for 0.79)
+2025-03-11 11:11:14.525 [scheduling-1] INFO  com.alibaba.druid.pool.DruidDataSource - {dataSource-1} inited
+2025-03-11 11:11:14.823 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:兰州市 的天气数据
+2025-03-11 11:11:15.130 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:兰州市 日天气数据下载完成
+2025-03-11 11:11:15.130 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:城关区 的天气数据
+2025-03-11 11:11:15.317 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:城关区 日天气数据下载完成
+2025-03-11 11:11:20.323 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:七里河区 的天气数据
+2025-03-11 11:11:20.543 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:七里河区 日天气数据下载完成
+2025-03-11 11:11:25.549 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:西固区 的天气数据
+2025-03-11 11:11:25.783 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:西固区 日天气数据下载完成
+2025-03-11 11:11:30.789 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:安宁区 的天气数据
+2025-03-11 11:11:31.072 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:安宁区 日天气数据下载完成
+2025-03-11 11:11:36.077 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:红古区 的天气数据
+2025-03-11 11:11:36.367 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:红古区 日天气数据下载完成
+2025-03-11 11:11:41.370 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:永登县 的天气数据
+2025-03-11 11:11:41.671 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:永登县 日天气数据下载完成
+2025-03-11 11:11:46.676 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:皋兰县 的天气数据
+2025-03-11 11:11:46.943 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:皋兰县 日天气数据下载完成
+2025-03-11 11:11:51.949 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:榆中县 的天气数据
+2025-03-11 11:11:52.172 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:榆中县 日天气数据下载完成
+2025-03-11 11:11:57.180 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:嘉峪关市 的天气数据
+2025-03-11 11:11:57.417 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:嘉峪关市 日天气数据下载完成
+2025-03-11 11:11:57.418 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:金昌市 的天气数据
+2025-03-11 11:11:57.527 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:金昌市 日天气数据下载完成
+2025-03-11 11:11:57.528 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:金川区 的天气数据
+2025-03-11 11:11:57.626 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:金川区 日天气数据下载完成
+2025-03-11 11:12:02.633 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:永昌县 的天气数据
+2025-03-11 11:12:02.867 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:永昌县 日天气数据下载完成
+2025-03-11 11:12:07.875 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:白银市 的天气数据
+2025-03-11 11:12:08.090 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:白银市 日天气数据下载完成
+2025-03-11 11:12:08.090 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:白银区 的天气数据
+2025-03-11 11:12:08.308 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:白银区 日天气数据下载完成
+2025-03-11 11:12:13.314 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:平川区 的天气数据
+2025-03-11 11:12:13.590 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:平川区 日天气数据下载完成
+2025-03-11 11:12:18.596 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:靖远县 的天气数据
+2025-03-11 11:12:18.897 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:靖远县 日天气数据下载完成
+2025-03-11 11:12:23.903 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:会宁县 的天气数据
+2025-03-11 11:12:24.145 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:会宁县 日天气数据下载完成
+2025-03-11 11:12:29.149 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:景泰县 的天气数据
+2025-03-11 11:12:29.398 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:景泰县 日天气数据下载完成
+2025-03-11 11:12:34.402 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:天水市 的天气数据
+2025-03-11 11:12:34.643 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:天水市 日天气数据下载完成
+2025-03-11 11:12:34.643 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:秦州区 的天气数据
+2025-03-11 11:12:34.747 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:秦州区 日天气数据下载完成
+2025-03-11 11:12:39.747 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:麦积区 的天气数据
+2025-03-11 11:12:39.963 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:麦积区 日天气数据下载完成
+2025-03-11 11:12:44.961 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:清水县 的天气数据
+2025-03-11 11:12:45.250 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:清水县 日天气数据下载完成
+2025-03-11 11:12:50.252 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:秦安县 的天气数据
+2025-03-11 11:12:50.490 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:秦安县 日天气数据下载完成
+2025-03-11 11:12:55.491 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:甘谷县 的天气数据
+2025-03-11 11:12:55.745 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:甘谷县 日天气数据下载完成
+2025-03-11 11:13:00.749 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:武山县 的天气数据
+2025-03-11 11:13:00.974 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:武山县 日天气数据下载完成
+2025-03-11 11:13:05.978 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:张家川回族自治县 的天气数据
+2025-03-11 11:13:06.206 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:张家川回族自治县 日天气数据下载完成
+2025-03-11 11:13:11.212 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:武威市 的天气数据
+2025-03-11 11:13:11.451 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:武威市 日天气数据下载完成
+2025-03-11 11:13:11.451 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:凉州区 的天气数据
+2025-03-11 11:13:11.638 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:凉州区 日天气数据下载完成
+2025-03-11 11:13:16.642 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:民勤县 的天气数据
+2025-03-11 11:13:16.909 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:民勤县 日天气数据下载完成
+2025-03-11 11:13:21.914 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:古浪县 的天气数据
+2025-03-11 11:13:22.172 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:古浪县 日天气数据下载完成
+2025-03-11 11:13:27.176 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:天祝藏族自治县 的天气数据
+2025-03-11 11:13:27.466 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:天祝藏族自治县 日天气数据下载完成
+2025-03-11 11:13:32.473 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:张掖市 的天气数据
+2025-03-11 11:13:32.770 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:张掖市 日天气数据下载完成
+2025-03-11 11:13:32.770 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:甘州区 的天气数据
+2025-03-11 11:13:32.886 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:甘州区 日天气数据下载完成
+2025-03-11 11:13:37.893 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:肃南裕固族自治县 的天气数据
+2025-03-11 11:13:38.105 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:肃南裕固族自治县 日天气数据下载完成
+2025-03-11 11:13:43.110 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:民乐县 的天气数据
+2025-03-11 11:13:43.325 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:民乐县 日天气数据下载完成
+2025-03-11 11:13:48.331 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:临泽县 的天气数据
+2025-03-11 11:13:48.738 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:临泽县 日天气数据下载完成
+2025-03-11 11:13:53.742 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:高台县 的天气数据
+2025-03-11 11:13:53.984 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:高台县 日天气数据下载完成
+2025-03-11 11:13:58.985 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:山丹县 的天气数据
+2025-03-11 11:13:59.182 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:山丹县 日天气数据下载完成
+2025-03-11 11:14:04.188 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:平凉市 的天气数据
+2025-03-11 11:14:04.401 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:平凉市 日天气数据下载完成
+2025-03-11 11:14:04.401 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:崆峒区 的天气数据
+2025-03-11 11:14:04.486 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:崆峒区 日天气数据下载完成
+2025-03-11 11:14:09.491 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:泾川县 的天气数据
+2025-03-11 11:14:09.724 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:泾川县 日天气数据下载完成
+2025-03-11 11:14:14.730 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:灵台县 的天气数据
+2025-03-11 11:14:14.972 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:灵台县 日天气数据下载完成
+2025-03-11 11:14:19.977 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:崇信县 的天气数据
+2025-03-11 11:14:20.207 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:崇信县 日天气数据下载完成
+2025-03-11 11:14:25.213 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:庄浪县 的天气数据
+2025-03-11 11:14:25.429 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:庄浪县 日天气数据下载完成
+2025-03-11 11:14:30.435 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:静宁县 的天气数据
+2025-03-11 11:14:30.637 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:静宁县 日天气数据下载完成
+2025-03-11 11:14:35.642 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:华亭市 的天气数据
+2025-03-11 11:14:35.873 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:华亭市 日天气数据下载完成
+2025-03-11 11:14:40.881 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:酒泉市 的天气数据
+2025-03-11 11:14:41.120 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:酒泉市 日天气数据下载完成
+2025-03-11 11:14:41.120 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:肃州区 的天气数据
+2025-03-11 11:14:41.310 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:肃州区 日天气数据下载完成
+2025-03-11 11:14:46.319 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:金塔县 的天气数据
+2025-03-11 11:14:46.565 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:金塔县 日天气数据下载完成
+2025-03-11 11:14:51.571 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:瓜州县 的天气数据
+2025-03-11 11:14:51.813 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:瓜州县 日天气数据下载完成
+2025-03-11 11:14:56.818 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:肃北蒙古族自治县 的天气数据
+2025-03-11 11:14:57.148 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:肃北蒙古族自治县 日天气数据下载完成
+2025-03-11 11:15:02.153 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:阿克塞哈萨克族自治县 的天气数据
+2025-03-11 11:15:02.468 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:阿克塞哈萨克族自治县 日天气数据下载完成
+2025-03-11 11:15:07.474 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:玉门市 的天气数据
+2025-03-11 11:15:07.724 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:玉门市 日天气数据下载完成
+2025-03-11 11:15:12.730 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:敦煌市 的天气数据
+2025-03-11 11:15:12.973 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:敦煌市 日天气数据下载完成
+2025-03-11 11:15:17.977 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:庆阳市 的天气数据
+2025-03-11 11:15:18.178 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:庆阳市 日天气数据下载完成
+2025-03-11 11:15:18.178 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:西峰区 的天气数据
+2025-03-11 11:15:18.268 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:西峰区 日天气数据下载完成
+2025-03-11 11:15:23.273 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:庆城县 的天气数据
+2025-03-11 11:15:23.501 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:庆城县 日天气数据下载完成
+2025-03-11 11:15:28.507 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:环县 的天气数据
+2025-03-11 11:15:28.734 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:环县 日天气数据下载完成
+2025-03-11 11:15:33.740 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:华池县 的天气数据
+2025-03-11 11:15:33.964 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:华池县 日天气数据下载完成
+2025-03-11 11:15:38.970 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:合水县 的天气数据
+2025-03-11 11:15:39.188 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:合水县 日天气数据下载完成
+2025-03-11 11:15:44.193 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:正宁县 的天气数据
+2025-03-11 11:15:44.404 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:正宁县 日天气数据下载完成
+2025-03-11 11:15:49.410 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:宁县 的天气数据
+2025-03-11 11:15:49.708 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:宁县 日天气数据下载完成
+2025-03-11 11:15:54.713 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:镇原县 的天气数据
+2025-03-11 11:15:54.953 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:镇原县 日天气数据下载完成
+2025-03-11 11:15:59.960 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:定西市 的天气数据
+2025-03-11 11:16:00.223 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:定西市 日天气数据下载完成
+2025-03-11 11:16:00.223 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:安定区 的天气数据
+2025-03-11 11:16:00.346 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:安定区 日天气数据下载完成
+2025-03-11 11:16:05.351 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:通渭县 的天气数据
+2025-03-11 11:16:05.713 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:通渭县 日天气数据下载完成
+2025-03-11 11:16:10.720 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:陇西县 的天气数据
+2025-03-11 11:16:10.984 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:陇西县 日天气数据下载完成
+2025-03-11 11:16:15.986 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:渭源县 的天气数据
+2025-03-11 11:16:16.309 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:渭源县 日天气数据下载完成
+2025-03-11 11:16:21.312 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:临洮县 的天气数据
+2025-03-11 11:16:21.618 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:临洮县 日天气数据下载完成
+2025-03-11 11:16:26.623 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:漳县 的天气数据
+2025-03-11 11:16:26.940 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:漳县 日天气数据下载完成
+2025-03-11 11:16:31.945 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:岷县 的天气数据
+2025-03-11 11:16:32.189 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:岷县 日天气数据下载完成
+2025-03-11 11:16:37.192 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:陇南市 的天气数据
+2025-03-11 11:16:37.399 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:陇南市 日天气数据下载完成
+2025-03-11 11:16:37.399 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:武都区 的天气数据
+2025-03-11 11:16:37.562 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:武都区 日天气数据下载完成
+2025-03-11 11:16:42.566 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:成县 的天气数据
+2025-03-11 11:16:42.804 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:成县 日天气数据下载完成
+2025-03-11 11:16:47.807 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:文县 的天气数据
+2025-03-11 11:16:48.022 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:文县 日天气数据下载完成
+2025-03-11 11:16:53.030 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:宕昌县 的天气数据
+2025-03-11 11:16:53.459 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:宕昌县 日天气数据下载完成
+2025-03-11 11:16:58.464 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:康县 的天气数据
+2025-03-11 11:16:59.036 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:康县 日天气数据下载完成
+2025-03-11 11:17:04.041 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:西和县 的天气数据
+2025-03-11 11:17:04.287 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:西和县 日天气数据下载完成
+2025-03-11 11:17:09.292 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:礼县 的天气数据
+2025-03-11 11:17:09.537 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:礼县 日天气数据下载完成
+2025-03-11 11:17:14.543 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:徽县 的天气数据
+2025-03-11 11:17:14.788 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:徽县 日天气数据下载完成
+2025-03-11 11:17:19.794 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:两当县 的天气数据
+2025-03-11 11:17:20.176 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:两当县 日天气数据下载完成
+2025-03-11 11:17:25.183 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:临夏回族自治州 的天气数据
+2025-03-11 11:17:25.522 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:临夏回族自治州 日天气数据下载完成
+2025-03-11 11:17:25.522 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:临夏市 的天气数据
+2025-03-11 11:17:25.666 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:临夏市 日天气数据下载完成
+2025-03-11 11:17:30.672 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:临夏县 的天气数据
+2025-03-11 11:17:30.889 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:临夏县 日天气数据下载完成
+2025-03-11 11:17:35.894 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:康乐县 的天气数据
+2025-03-11 11:17:36.127 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:康乐县 日天气数据下载完成
+2025-03-11 11:17:41.132 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:永靖县 的天气数据
+2025-03-11 11:17:41.366 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:永靖县 日天气数据下载完成
+2025-03-11 11:17:46.372 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:广河县 的天气数据
+2025-03-11 11:17:46.596 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:广河县 日天气数据下载完成
+2025-03-11 11:17:51.600 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:和政县 的天气数据
+2025-03-11 11:17:51.826 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:和政县 日天气数据下载完成
+2025-03-11 11:17:56.832 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:东乡族自治县 的天气数据
+2025-03-11 11:17:57.087 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:东乡族自治县 日天气数据下载完成
+2025-03-11 11:18:02.093 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:积石山保安族东乡族撒拉族自治县 的天气数据
+2025-03-11 11:18:02.350 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:积石山保安族东乡族撒拉族自治县 日天气数据下载完成
+2025-03-11 11:18:07.359 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:甘南藏族自治州 的天气数据
+2025-03-11 11:18:07.609 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:甘南藏族自治州 日天气数据下载完成
+2025-03-11 11:18:07.610 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:合作市 的天气数据
+2025-03-11 11:18:07.711 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:合作市 日天气数据下载完成
+2025-03-11 11:18:12.717 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:临潭县 的天气数据
+2025-03-11 11:18:12.948 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:临潭县 日天气数据下载完成
+2025-03-11 11:18:17.954 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:卓尼县 的天气数据
+2025-03-11 11:18:18.168 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:卓尼县 日天气数据下载完成
+2025-03-11 11:18:23.174 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:舟曲县 的天气数据
+2025-03-11 11:18:23.385 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:舟曲县 日天气数据下载完成
+2025-03-11 11:18:28.391 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:迭部县 的天气数据
+2025-03-11 11:18:28.605 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:迭部县 日天气数据下载完成
+2025-03-11 11:18:33.611 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:玛曲县 的天气数据
+2025-03-11 11:18:33.826 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:玛曲县 日天气数据下载完成
+2025-03-11 11:18:38.832 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:碌曲县 的天气数据
+2025-03-11 11:18:39.059 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:碌曲县 日天气数据下载完成
+2025-03-11 11:18:44.065 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 开始下载地区:夏河县 的天气数据
+2025-03-11 11:18:44.253 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气,地区:夏河县 日天气数据下载完成
+2025-03-11 11:18:49.842 [scheduling-1] INFO  com.example.getweather.service.GetWeather - 彩云天气数据全部下载完毕
+2025-03-11 11:19:10.893 [Thread-3] INFO  com.alibaba.druid.pool.DruidDataSource - {dataSource-1} closed

+ 136 - 0
pom.xml

@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+         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.example</groupId>
+    <artifactId>getWeather</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>getWeather</name>
+    <description>getWeather</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.6.13</spring-boot.version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid</artifactId>
+            <version>1.1.14</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.8.16</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.12</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>8.0.25</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-net</groupId>
+            <artifactId>commons-net</artifactId>
+            <version>3.6</version>
+        </dependency>
+        <dependency>
+            <groupId>com.taosdata.jdbc</groupId>
+            <artifactId>taos-jdbcdriver</artifactId>
+            <version>3.2.5</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.ant</groupId>
+            <artifactId>ant</artifactId>
+            <version>1.8.1</version>
+        </dependency>
+        <dependency>
+            <groupId>com.github.junrar</groupId>
+            <artifactId>junrar</artifactId>
+            <version>0.7</version>
+        </dependency>
+        <dependency>
+            <groupId>com.jcraft</groupId>
+            <artifactId>jsch</artifactId> <!-- 解决 sftp 连接 -->
+            <version>0.1.55</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-compress</artifactId>
+            <version>1.21</version>
+        </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>8</source>
+                    <target>8</target>
+                    <encoding>UTF-8</encoding>
+                </configuration>
+            </plugin>
+            <!-- 打包过程忽略Junit测试 -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>2.17</version>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>${spring-boot.version}</version>
+                <configuration>
+                    <mainClass>com.example.getweather.GetWeatherApplication</mainClass>
+                    <!--<skip>true</skip>-->
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>repackage</id>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 15 - 0
src/main/java/com/example/getweather/GetWeatherApplication.java

@@ -0,0 +1,15 @@
+package com.example.getweather;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+@EnableScheduling
+@SpringBootApplication
+public class GetWeatherApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(GetWeatherApplication.class, args);
+    }
+
+}

+ 58 - 0
src/main/java/com/example/getweather/entity/DistrictCodeDO.java

@@ -0,0 +1,58 @@
+package com.example.getweather.entity;
+
+import lombok.*;
+
+/**
+ * 行政区划 DO
+ *
+ * @author 嘉越电力
+ */
+@Data
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class DistrictCodeDO {
+
+    /**
+     * 行政区划代码
+     */
+    private Integer code;
+    /**
+     * 名字
+     */
+    private String name;
+    /**
+     * 等级:1-省级;2-地级市;3-区/县;4-乡/镇
+     */
+    private Integer level;
+    /**
+     * 类型:1-省;2-自治区;3-直辖市;4-特别行政区;5-地级市;6-地区;7-自治州;8-盟;9-市辖区;10-县;11- 县级市;12-自治县;13-旗;14-自治旗;15-特区;16-林区
+     */
+    private Integer type;
+    /**
+     * 简称
+     */
+    private String abname;
+    /**
+     * 所属行政区划代码
+     */
+    private Integer pid;
+    /**
+     * 所属行政区划名字
+     */
+    private String pname;
+    /**
+     * 备注
+     */
+    private String note;
+    /**
+     * 纬度
+     */
+    private Double lat;
+    /**
+     * 经度
+     */
+    private Double lng;
+
+}

+ 115 - 0
src/main/java/com/example/getweather/entity/HeFengDay.java

@@ -0,0 +1,115 @@
+package com.example.getweather.entity;
+
+import lombok.*;
+
+import java.sql.Timestamp;
+
+/**
+ * 和风天气数据(日)
+ */
+@Data
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class HeFengDay {
+    /**
+     * 时间
+     */
+    private Timestamp ts;
+
+    /**
+     * 国标码
+     */
+    private String areaCode;
+
+    /**
+     * 预报当天最高温度
+     */
+    private float tempMax;
+
+    /**
+     * 预报当天最低温度
+     */
+    private float tempMin;
+
+    /**
+     * 预报白天天气状况文字描述,包括阴晴雨雪等天气状态的描述
+     */
+    private String textDay;
+
+    /**
+     * 预报晚间天气状况文字描述,包括阴晴雨雪等天气状态的描述
+     */
+    private String textNight;
+
+    /**
+     * 预报白天风向360角度
+     */
+    private float wind360Day;
+
+    /**
+     * 预报白天风向
+     */
+    private String windDirDay;
+
+    /**
+     * 预报白天风力等级
+     */
+    private int windScaleDay;
+
+    /**
+     * 预报白天风速,公里/小时
+     */
+    private float windSpeedDay;
+    /**
+     * 预报白天风速,米/秒
+     */
+    private float windSpeedMDay;
+
+    /**
+     * 预报夜间风向360角度
+     */
+    private float wind360Night;
+
+    /**
+     * 预报夜间当天风向
+     */
+    private String windDirNight;
+
+    /**
+     * 预报夜间风力等级
+     */
+    private int windScaleNight;
+
+    /**
+     * 预报夜间风速,公里/小时
+     */
+    private float windSpeedNight;
+    /**
+     * 预报夜间风速,米/秒
+     */
+    private float windSpeedMNight;
+
+    /**
+     * 预报当天总降水量,默认单位:毫米
+     */
+    private float humidity;
+
+    /**
+     * 相对湿度,百分比数值
+     */
+    private float precip;
+
+    /**
+     * 大气压强,默认单位:百帕
+     */
+    private float pressure;
+
+    /**
+     * 向下短波辐射通量(W/M2)
+     */
+    private float dswrf;
+
+
+}

+ 50 - 0
src/main/java/com/example/getweather/entity/HeFengHour.java

@@ -0,0 +1,50 @@
+package com.example.getweather.entity;
+
+import lombok.*;
+
+import java.sql.Timestamp;
+
+/**
+ * 和风天气数据(小时)
+ */
+@Data
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class HeFengHour {
+
+    private Timestamp ts;
+    //温度,默认单位:摄氏度
+    private float temp;
+    /**
+     * 国标码
+     */
+    private String areaCode;
+    //天气状况的文字描述,包括阴晴雨雪等天气状态的描述
+    private String text;
+    //风向
+    private String windDir;
+    //风向360角度
+    private float wind360;
+    //风速,公里/小时
+    private float windSpeed;
+    //风速,米/秒
+    private float windSpeedM;
+    //风力等级
+    private float windScale;
+    //云量,百分比数值。可能为空
+    private float cloud;
+    //当前小时累计降水量,默认单位:毫米
+    private float precip;
+    //露点温度。可能为空
+    private float dew;
+    //相对湿度
+    private float humidity;
+    //地面气压 彩云接口
+    private float pressure;
+    //向下短波辐射通量(W/M2) 彩云接口
+    private float dswrf;
+
+
+}

+ 25 - 0
src/main/java/com/example/getweather/job/Download.java

@@ -0,0 +1,25 @@
+package com.example.getweather.job;
+
+import com.example.getweather.service.GetWeather;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+
+@Slf4j
+@Service
+@EnableScheduling
+public class Download {
+    @Resource
+    private GetWeather getWeather;
+
+    //每天0点下载数据     2025-02-10 应窦哥要求 小时气象源切换为xmo 日的还用彩云
+    //@Scheduled(fixedDelay = 600000000)
+    @Scheduled(cron = "0 15 1 * * ?")
+    public void download() {
+        getWeather.download();
+    }
+}

+ 26 - 0
src/main/java/com/example/getweather/job/DownloadXmo.java

@@ -0,0 +1,26 @@
+package com.example.getweather.job;
+
+import com.example.getweather.service.GetWeatherXmo;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+
+@Slf4j
+@Service
+@EnableScheduling
+public class DownloadXmo {
+    @Resource
+    private GetWeatherXmo getWeatherXmo;
+
+    //曦谋数据接入。    2025-02-10 应窦哥要求 小时气象源切换为xmo
+    //每天1点下载数据
+    //@Scheduled(fixedDelay = 600000000)
+    @Scheduled(cron = "0 0 9,13 * * ?")
+    public void download() {
+        getWeatherXmo.download();
+    }
+}

+ 23 - 0
src/main/java/com/example/getweather/job/XmoComplementsJob.java

@@ -0,0 +1,23 @@
+package com.example.getweather.job;
+
+import com.example.getweather.service.XmoComplements;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+
+@Slf4j
+@Service
+@EnableScheduling
+public class XmoComplementsJob {
+    @Resource
+    private XmoComplements xmoComplements;
+
+    //曦谋数据补数
+    //@Scheduled(fixedDelay = 600000000)
+    public void download() {
+        xmoComplements.download();
+    }
+}

+ 580 - 0
src/main/java/com/example/getweather/service/GetWeather.java

@@ -0,0 +1,580 @@
+package com.example.getweather.service;
+
+import cn.hutool.db.Db;
+import cn.hutool.db.Entity;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.example.getweather.entity.DistrictCodeDO;
+import com.example.getweather.entity.HeFengDay;
+import com.example.getweather.util.WeixinPush;
+import com.taosdata.jdbc.TSDBDriver;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.Statement;
+import java.sql.Timestamp;
+import java.time.Instant;
+import java.time.ZonedDateTime;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+@Validated
+@Slf4j
+public class GetWeather {
+    @Resource
+    private WeixinPush weixinPush;
+    /*public void download() {
+
+        List<String> areaCodes = new ArrayList<>();
+        List<DistrictCodeDO> districtCodeDOList = new ArrayList<>();
+
+        try {
+            List<Entity> dictList = Db.use().findAll("system_dict_data");
+            for (Entity entity : dictList) {
+                String name = entity.getStr("label");
+                if (name.contains("area_code")) {
+                    String code = entity.getStr("value");
+                    String[] s = code.split(",");
+                    areaCodes = Arrays.asList(s);
+                }
+            }
+            List<Entity> districtCodes = Db.use().findAll("jy_district_code");
+            for (Entity e : districtCodes) {
+                DistrictCodeDO districtCodeDO = new DistrictCodeDO();
+                districtCodeDO.setCode(Integer.parseInt(e.getStr("code")));
+                districtCodeDO.setName(e.getStr("name"));
+                districtCodeDO.setLevel(Integer.parseInt(e.getStr("level")));
+                districtCodeDO.setType(Integer.parseInt(e.getStr("type")));
+                districtCodeDO.setAbname(e.getStr("abname"));
+                districtCodeDO.setPid(Integer.parseInt(e.getStr("pid")));
+                districtCodeDO.setLat(!Objects.equals(e.getStr("lat"), "") && e.getStr("lat") != null ? new BigDecimal(e.getStr("lat")).setScale(6, RoundingMode.HALF_UP).doubleValue() : 0d);
+                districtCodeDO.setLng(!Objects.equals(e.getStr("lng"), "") && e.getStr("lng") != null ? new BigDecimal(e.getStr("lng")).setScale(6, RoundingMode.HALF_UP).doubleValue() : 0d);
+                districtCodeDOList.add(districtCodeDO);
+            }
+            String jdbcUrl = "jdbc:TAOS://192.168.12.241:19500/etadm_local?user=root&password=qE$#6G0zROoc";
+            Properties connProps = new Properties();
+            connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
+            connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
+            connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
+            Connection conn = DriverManager.getConnection(jdbcUrl, connProps);
+            //省份
+            for (String code : areaCodes) {
+                List<DistrictCodeDO> shiList = districtCodeDOList.stream().filter(item -> item.getPid().toString().equals(code)).collect(Collectors.toList());
+                //市
+                for (DistrictCodeDO d : shiList) {
+                    List<DistrictCodeDO> quList = districtCodeDOList.stream().filter(item -> item.getPid().toString().equals(d.getCode().toString())).collect(Collectors.toList());
+                    log.info("开始下载地区:{} 的天气数据", d.getName());
+                    String hefeng24;
+                    String caiyun24;
+                    String hefengDay;
+                    String caiyunDay;
+                    //!!!!!!!!!!拼的彩云的辐照度!!!!!!!!!!!!!
+                    //和风逐小时数据
+                    hefeng24 = "https://devapi.qweather.com/v7/grid-weather/24h?location=" + d.getLng() + "," + d.getLat() + "&key=54d9633382814e148836ce6be2d003fb";
+                    //彩云逐小时数据
+                    caiyun24 = "https://api.caiyunapp.com/v2.6/SRQIFijX5MGtdmhe/" + d.getLng() + "," + d.getLat() + "/hourly?hourlysteps=24";
+                    //和风逐日数据
+                    hefengDay = "https://devapi.qweather.com/v7/grid-weather/7d?location=" + d.getLng() + "," + d.getLat() + "&key=54d9633382814e148836ce6be2d003fb";
+                    //彩云逐日数据
+                    caiyunDay = "https://api.caiyunapp.com/v2.6/SRQIFijX5MGtdmhe/" + d.getLng() + "," + d.getLat() + "/daily?dailysteps=7";
+                    analysis24(hefeng24, caiyun24, d.getCode(), d.getName(), conn);
+                    analysisDay(hefengDay, caiyunDay, d.getCode(), d.getName(), conn);
+                    //区
+                    for (DistrictCodeDO q : quList) {
+                        log.info("开始下载地区:{} 的天气数据", q.getName());
+                        //和风逐小时数据
+                        hefeng24 = "https://devapi.qweather.com/v7/grid-weather/24h?location=" + q.getLng() + "," + q.getLat() + "&key=54d9633382814e148836ce6be2d003fb";
+                        //彩云逐小时数据
+                        caiyun24 = "https://api.caiyunapp.com/v2.6/SRQIFijX5MGtdmhe/" + q.getLng() + "," + q.getLat() + "/hourly?hourlysteps=24";
+                        //和风逐日数据
+                        hefengDay = "https://devapi.qweather.com/v7/grid-weather/7d?location=" + q.getLng() + "," + q.getLat() + "&key=54d9633382814e148836ce6be2d003fb";
+                        //彩云逐日数据
+                        caiyunDay = "https://api.caiyunapp.com/v2.6/SRQIFijX5MGtdmhe/" + q.getLng() + "," + q.getLat() + "/daily?dailysteps=7";
+                        analysis24(hefeng24, caiyun24, q.getCode(), q.getName(), conn);
+                        analysisDay(hefengDay, caiyunDay, q.getCode(), q.getName(), conn);
+                    }
+                }
+            }
+            conn.close();
+            log.info("天气数据全部下载完毕");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }*/
+
+
+    /**
+     * 根据风速获取对应风力等级
+     * 2025-01-09 改为km/h单位
+     *
+     * @param speed 风速,单位为 km/h
+     * @return 风力等级
+     */
+    public static int speedLevel(String speed) {
+        BigDecimal val = new BigDecimal(speed);
+        //<0.3	无风 0级
+        if (val.compareTo(new BigDecimal("1")) < 0) {
+            return 0;
+        } else if (val.compareTo(new BigDecimal("6")) < 0) {
+            //0.3-1.6	微风徐徐 1级
+            return 1;
+        } else if (val.compareTo(new BigDecimal("12")) < 0) {
+            //1.6-3.4	清风 2级
+            return 2;
+        } else if (val.compareTo(new BigDecimal("20")) < 0) {
+            //3.4-5.5	树叶摇摆 3级
+            return 3;
+        } else if (val.compareTo(new BigDecimal("29")) < 0) {
+            //5.5-8.0	树枝摇动 4级
+            return 4;
+        } else if (val.compareTo(new BigDecimal("39")) < 0) {
+            //8.0-10.8	风吹折小树 5级
+            return 5;
+        } else if (val.compareTo(new BigDecimal("50")) < 0) {
+            //10.8-13.9	树枝折断 6级
+            return 6;
+        } else if (val.compareTo(new BigDecimal("62")) < 0) {
+            //13.9-17.2	风吹倒树木 7级
+            return 7;
+        } else if (val.compareTo(new BigDecimal("75")) < 0) {
+            //17.2-20.8	风吹断大树 8级
+            return 8;
+        } else if (val.compareTo(new BigDecimal("89")) < 0) {
+            //20.8-24.5	强风 9级
+            return 9;
+        } else if (val.compareTo(new BigDecimal("103")) < 0) {
+            //24.5-28.5	狂风 10级
+            return 10;
+        } else if (val.compareTo(new BigDecimal("117")) < 0) {
+            //28.5-32.7	暴风 11级
+            return 11;
+        } else if (val.compareTo(new BigDecimal("134")) < 0) {
+            //32.7-37.0	大暴风 12级
+            return 12;
+        } else if (val.compareTo(new BigDecimal("150")) < 0) {
+            //37.0-41.5	飓风 13级
+            return 13;
+        } else if (val.compareTo(new BigDecimal("167")) < 0) {
+            //41.5-46.2	强飓风 14级
+            return 14;
+        } else if (val.compareTo(new BigDecimal("184")) < 0) {
+            //46.2-50.9	猛烈飓风 15级
+            return 15;
+        } else if (val.compareTo(new BigDecimal("202")) < 0) {
+            //50.9-56.1	毁灭性飓风 16级
+            return 16;
+        } else {
+            //56.1-61.3	超级飓风 17级
+            return 17;
+        }
+    }
+
+
+    public void download() {
+        List<String> areaCodes = new ArrayList<>();
+        List<DistrictCodeDO> districtCodeDOList = new ArrayList<>();
+        boolean isApiQuotaExhausted = false; // 引入标志变量
+
+        try {
+            List<Entity> dictList = Db.use().findAll("system_dict_data");
+            for (Entity entity : dictList) {
+                String name = entity.getStr("label");
+                if (name.contains("area_code")) {
+                    String code = entity.getStr("value");
+                    String[] s = code.split(",");
+                    areaCodes = Arrays.asList(s);
+                }
+            }
+            List<Entity> districtCodes = Db.use().findAll("jy_district_code");
+            for (Entity e : districtCodes) {
+                DistrictCodeDO districtCodeDO = new DistrictCodeDO();
+                districtCodeDO.setCode(Integer.parseInt(e.getStr("code")));
+                districtCodeDO.setName(e.getStr("name"));
+                districtCodeDO.setLevel(Integer.parseInt(e.getStr("level")));
+                districtCodeDO.setType(Integer.parseInt(e.getStr("type")));
+                districtCodeDO.setAbname(e.getStr("abname"));
+                districtCodeDO.setPid(Integer.parseInt(e.getStr("pid")));
+                districtCodeDO.setLat(!Objects.equals(e.getStr("lat"), "") && e.getStr("lat") != null ? new BigDecimal(e.getStr("lat")).setScale(6, RoundingMode.HALF_UP).doubleValue() : 0d);
+                districtCodeDO.setLng(!Objects.equals(e.getStr("lng"), "") && e.getStr("lng") != null ? new BigDecimal(e.getStr("lng")).setScale(6, RoundingMode.HALF_UP).doubleValue() : 0d);
+                districtCodeDOList.add(districtCodeDO);
+            }
+            String jdbcUrl = "jdbc:TAOS://192.168.12.241:19500/etadm_local?user=root&password=qE$#6G0zROoc";
+            Properties connProps = new Properties();
+            connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
+            connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
+            connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
+            Connection conn = DriverManager.getConnection(jdbcUrl, connProps);
+            //省份
+            for (String code : areaCodes) {
+                if (isApiQuotaExhausted) break; // 检查标志变量
+                List<DistrictCodeDO> shiList = districtCodeDOList.stream().filter(item -> item.getPid().toString().equals(code)).collect(Collectors.toList());
+                //市
+                for (DistrictCodeDO d : shiList) {
+                    if (isApiQuotaExhausted) break; // 检查标志变量
+                    List<DistrictCodeDO> quList = districtCodeDOList.stream().filter(item -> item.getPid().toString().equals(d.getCode().toString())).collect(Collectors.toList());
+                    String caiyun;
+                    //彩云综合数据查询
+                    caiyun = "https://api.caiyunapp.com/v2.6/SRQIFijX5MGtdmhe/" + d.getLng() + "," + d.getLat() + "/weather?alert=true&dailysteps=7&hourlysteps=72";
+                    isApiQuotaExhausted = analysis(caiyun, d.getCode(), d.getName(), conn); // 传递标志变量
+                    if (isApiQuotaExhausted) break; // 检查标志变量
+                    //区
+                    for (DistrictCodeDO q : quList) {
+                        if (isApiQuotaExhausted) break; // 检查标志变量
+                        caiyun = "https://api.caiyunapp.com/v2.6/SRQIFijX5MGtdmhe/" + q.getLng() + "," + q.getLat() + "/weather?alert=true&dailysteps=7&hourlysteps=72";
+                        isApiQuotaExhausted = analysis(caiyun, q.getCode(), q.getName(), conn); // 传递标志变量
+                        if (isApiQuotaExhausted) break; // 检查标志变量
+                        //线程睡5秒 防止请求过快
+                        Thread.sleep(5000);
+                    }
+                }
+            }
+            conn.close();
+            String alarm = "电力交易系统在获取日级天气数据时报错, 彩云天气API 额度已用尽";
+            String description = "接口调用异常";
+            if (isApiQuotaExhausted) {
+                //给企业微信发送消息
+             /*   WeixinPush weixinPush = new WeixinPush();
+                WeixinMessage weixinMessage = new WeixinMessage();
+                weixinMessage.setToUser("WangHongChen|XiuWei|DouZhi");
+                //获取今天的ymd
+                String ymd = DateUtil.format(DateUtil.date(), "yyyy-MM-dd");
+                weixinMessage.setContent(ymd + "日 电力交易系统在获取天气数据时报错, 彩云天气API 额度已用尽");
+                weixinMessage.setMsgType("text");
+                weixinMessage.setAgentid(1000009); // 确保 agentid 正确
+                 weixinPush.sendMessage(weixinMessage);
+                */
+                weixinPush.sendMessageBot(alarm, description);
+            } else {
+                alarm = "电力交易系统彩云天气数据全部下载完毕";
+                description = "接口调用成功";
+                weixinPush.sendMessageBot(alarm, description);
+                log.info("彩云天气数据全部下载完毕");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /*public void analysis24(String hefeng24url, String caiyun24url, int areaCode, String name, Connection conn) {
+        try {
+            Statement ps = conn.createStatement();
+            String caiyunBody = HttpUtil.createGet(caiyun24url).execute().charset("utf-8").body();
+            JSONObject caiyunjsonObject = JSONUtil.parseObj(caiyunBody);
+            JSONObject caiyunResult = JSONUtil.parseObj(caiyunjsonObject.get("result"));
+            JSONObject hourly = JSONUtil.parseObj(caiyunResult.get("hourly"));
+            JSONArray dswrf = JSONUtil.parseArray(hourly.get("dswrf"));
+
+            String hefengBody = HttpUtil.createGet(hefeng24url).execute().charset("utf-8").body();
+            JSONObject jsonObject = JSONUtil.parseObj(hefengBody);
+            JSONArray hefengList = JSONUtil.parseArray(jsonObject.get("hourly"));
+            List<HeFengHour> list = new ArrayList<>();
+            hefengList.forEach(item -> {
+                JSONObject jsonObject1 = JSONUtil.parseObj(item);
+                try {
+                    HeFengHour weather = new HeFengHour();
+                    String s = jsonObject1.getStr("fxTime");
+                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mmXXX");
+                    ZonedDateTime zonedDateTime = ZonedDateTime.parse(s, formatter);
+                    Instant instant = zonedDateTime.toInstant();
+                    Timestamp timestamp = Timestamp.from(instant);
+                    weather.setTs(timestamp);
+                    weather.setTemp(new BigDecimal(jsonObject1.getStr("temp")).floatValue());
+                    weather.setAreaCode(String.valueOf(areaCode));
+                    weather.setText(jsonObject1.getStr("text"));
+                    weather.setWindDir(jsonObject1.getStr("windDir"));
+                    weather.setWind360(new BigDecimal(jsonObject1.getStr("wind360")).floatValue());
+                    weather.setWindSpeed(new BigDecimal(jsonObject1.getStr("windSpeed")).divide(new BigDecimal("3.6"), 2, RoundingMode.HALF_UP).floatValue());
+                    weather.setWindScale(new BigDecimal(jsonObject1.getStr("windScale")).floatValue());
+                    weather.setHumidity(new BigDecimal(jsonObject1.getStr("humidity")).floatValue());
+                    weather.setCloud(new BigDecimal(jsonObject1.getStr("cloud")).floatValue());
+                    weather.setPrecip(new BigDecimal(jsonObject1.getStr("precip")).floatValue());
+                    weather.setDew(new BigDecimal(jsonObject1.getStr("dew")).floatValue());
+                    weather.setPressure(new BigDecimal(jsonObject1.getStr("pressure")).floatValue());
+                    list.add(weather);
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            });
+            if (!dswrf.isEmpty()) {
+                if (list.size() != 24) {
+                    log.error("地区:{} 24小时天气数据下载失败,和风天气数据不全", name);
+                } else {
+                    if (dswrf.size() != 24) {
+                        log.error("地区:{} 24小时天气数据下载失败,心知天气数据不全", name);
+                    } else {
+                        for (int i = 0; i < 24; i++) {
+                            Map ds = (Map) dswrf.get(i);
+                            list.get(i).setDswrf(new BigDecimal(ds.get("value").toString()).floatValue());
+                        }
+                    }
+
+                }
+            }
+            for (HeFengHour item : list) {
+                String insertSql = " INSERT INTO hefeng_hour_unit_" + areaCode + " USING hefeng_hour_unit TAGS('" + areaCode + "') values('" + item.getTs() + "', " + item.getTemp() + ", '" + item.getText() + "', '" + item.getWindDir() + "', " + item.getWind360() + ", " + item.getWindSpeed() + ", " + item.getWindScale() + ", " + item.getHumidity() + ", " + item.getCloud() + ", " + item.getPrecip() + ", " + item.getDew() + ", " + item.getPressure() + ", " + item.getDswrf() + ")";
+                int affectedRows = ps.executeUpdate(insertSql);
+            }
+            if (ps != null)
+                ps.close();
+        } catch (Exception e) {
+            log.error("地区:{} 24小时天气数据下载失败JSON格式化错误", name);
+        }
+        log.info("地区:{} 24小时天气数据下载完成", name);
+    }
+
+    public void analysisDay(String hefeng24url, String caiyun24url, int areaCode, String name, Connection conn) {
+        try {
+            Statement ps = conn.createStatement();
+            String caiyunBody = HttpUtil.createGet(caiyun24url).execute().charset("utf-8").body();
+            JSONObject caiyunjsonObject = JSONUtil.parseObj(caiyunBody);
+            JSONObject caiyunResult = JSONUtil.parseObj(caiyunjsonObject.get("result"));
+            JSONObject daily = JSONUtil.parseObj(caiyunResult.get("daily"));
+            JSONArray dswrf = JSONUtil.parseArray(daily.get("dswrf"));
+
+            String hefengBody = HttpUtil.createGet(hefeng24url).execute().charset("utf-8").body();
+            JSONObject jsonObject = JSONUtil.parseObj(hefengBody);
+            JSONArray hefengList = JSONUtil.parseArray(jsonObject.get("daily"));
+            List<HeFengDay> list = new ArrayList<>();
+            hefengList.forEach(item -> {
+                JSONObject jsonObject1 = JSONUtil.parseObj(item);
+                try {
+                    HeFengDay weather = new HeFengDay();
+                    String s = jsonObject1.getStr("fxDate");
+                    LocalDate localDate = LocalDate.parse(s);
+                    // 将 LocalDate 转换为 Instant,然后再转换为 Timestamp
+                    Timestamp timestamp = Timestamp.valueOf(localDate.atStartOfDay(ZoneOffset.UTC).toLocalDateTime());
+                    weather.setTs(timestamp);
+                    weather.setAreaCode(String.valueOf(areaCode));
+                    weather.setTempMax(new BigDecimal(jsonObject1.getStr("tempMax")).floatValue());
+                    weather.setTempMin(new BigDecimal(jsonObject1.getStr("tempMin")).floatValue());
+                    weather.setTextDay(jsonObject1.getStr("textDay"));
+                    weather.setTextNight(jsonObject1.getStr("textNight"));
+                    weather.setWind360Day(new BigDecimal(jsonObject1.getStr("wind360Day")).floatValue());
+                    weather.setWind360Night(new BigDecimal(jsonObject1.getStr("wind360Night")).floatValue());
+                    weather.setWindDirDay(jsonObject1.getStr("windDirDay"));
+                    weather.setWindDirNight(jsonObject1.getStr("windDirNight"));
+                    weather.setWindScaleDay(new BigDecimal(jsonObject1.getStr("windScaleDay")).floatValue());
+                    weather.setWindScaleNight(new BigDecimal(jsonObject1.getStr("windScaleNight")).floatValue());
+                    weather.setWindSpeedDay(new BigDecimal(jsonObject1.getStr("windSpeedDay")).divide(new BigDecimal("3.6"), 2, RoundingMode.HALF_UP).floatValue());
+                    weather.setWindSpeedNight(new BigDecimal(jsonObject1.getStr("windSpeedNight")).divide(new BigDecimal("3.6"), 2, RoundingMode.HALF_UP).floatValue());
+                    weather.setHumidity(new BigDecimal(jsonObject1.getStr("humidity")).floatValue());
+                    weather.setPrecip(new BigDecimal(jsonObject1.getStr("precip")).floatValue());
+                    weather.setPressure(new BigDecimal(jsonObject1.getStr("pressure")).floatValue());
+                    list.add(weather);
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            });
+            if (!dswrf.isEmpty()) {
+                if (list.size() != 7) {
+                    log.error("地区:{} 日天气数据下载失败,和风天气数据不全", name);
+                } else {
+                    for (HeFengDay heFengDay : list) {
+                        Map ds = (Map) dswrf.get(0);
+                        heFengDay.setDswrf(new BigDecimal(ds.get("max").toString()).floatValue());
+                    }
+                }
+            }
+            for (HeFengDay item : list) {
+                String insertSQL = "INSERT INTO hefeng_day_unit_" + item.getAreaCode() + " USING hefeng_day_unit TAGS('" + item.getAreaCode() + "')  values('" + item.getTs() + "', " + item.getTempMax() + ", " + item.getTempMin() + ", '" + item.getTextDay() + "', '" + item.getTextNight() + "', " + item.getWind360Day() + ", '" + item.getWindDirDay() + "', " + item.getWindScaleDay() + ", " + item.getWindSpeedDay() + ", " + item.getWind360Night() + ", '" + item.getWindDirNight() + "', " + item.getWindScaleNight() + ", " + item.getWindSpeedNight() + ", " + item.getHumidity() + ", " + item.getPrecip() + ", " + item.getPressure() + ", " + item.getDswrf() + ")";
+                int affectedRows = ps.executeUpdate(insertSQL);
+            }
+            if (ps != null)
+                ps.close();
+        } catch (Exception e) {
+            log.error("地区:{} 日天气数据下载失败JSON格式化错误", name);
+        }
+        log.info("地区:{} 日天气数据下载完成", name);
+    }*/
+
+    public boolean analysis(String caiyun, int areaCode, String name, Connection conn) {
+        log.info("开始下载地区:{} 的天气数据", name);
+        try {
+            Statement ps = conn.createStatement();
+            String caiyunBody = HttpUtil.createGet(caiyun).execute().charset("utf-8").body();
+            JSONObject caiyunjsonObject = JSONUtil.parseObj(caiyunBody);
+            if (caiyunjsonObject.toString().contains("API quota is exhausted")) {
+                return true;
+            }
+            JSONObject caiyunResult = JSONUtil.parseObj(caiyunjsonObject.get("result"));
+            //小时数据 72小时
+            /*JSONObject hourly = JSONUtil.parseObj(caiyunResult.get("hourly"));
+            //小时->温度
+            JSONArray temperature = JSONUtil.parseArray(hourly.get("temperature"));
+            //小时->辐照度
+            JSONArray dswrf = JSONUtil.parseArray(hourly.get("dswrf"));
+            //小时->风速
+            JSONArray windSpeed = JSONUtil.parseArray(hourly.get("wind"));
+            //小时->天气标识
+            JSONArray skyconHour = JSONUtil.parseArray(hourly.get("skycon"));
+            //小时->湿度
+            JSONArray humidityHour = JSONUtil.parseArray(hourly.get("humidity"));
+            //小时->压强
+            JSONArray pressureHour = JSONUtil.parseArray(hourly.get("pressure"));*/
+            //日数据 7d
+            JSONObject daily = JSONUtil.parseObj(caiyunResult.get("daily"));
+            //日->辐照度
+            JSONArray dswrfDay = JSONUtil.parseArray(daily.get("dswrf"));
+            //日->温度
+            JSONArray temperatureDay = JSONUtil.parseArray(daily.get("temperature"));
+            //日->风速 8点到20点
+            JSONArray windSpeed8Day = JSONUtil.parseArray(daily.get("wind_08h_20h"));
+            //日->风速 20点到32点
+            JSONArray windSpeed20Day = JSONUtil.parseArray(daily.get("wind_20h_32h"));
+            //日->天气描述 8点到20点
+            JSONArray skycon8 = JSONUtil.parseArray(daily.get("skycon_08h_20h"));
+            //日->天气描述 20点到32点
+            JSONArray skycon20 = JSONUtil.parseArray(daily.get("skycon_20h_32h"));
+            //小时数据写入。  时间 风速 辐照度
+            /*List<HeFengHour> heFengHourList = new ArrayList<>();
+            if (windSpeed.size() == 72 && dswrf.size() == 72 && temperature.size() == 72) {
+                for (int i = 0; i < windSpeed.size(); i++) {
+                    String time = ((JSONObject) windSpeed.get(i)).get("datetime").toString();
+                    HeFengHour heFengHour = new HeFengHour();
+                    heFengHour.setTs(getTimestamp(time));
+                    heFengHour.setWindSpeed(new BigDecimal(((JSONObject) windSpeed.get(i)).get("speed").toString()).floatValue());
+                    heFengHour.setWindSpeedM(new BigDecimal(((JSONObject) windSpeed.get(i)).get("speed").toString()).floatValue() * 1000 / 3600);
+                    heFengHour.setWindScale(speedLevel(((JSONObject) windSpeed.get(i)).get("speed").toString()));
+                    heFengHour.setWind360(new BigDecimal(((JSONObject) windSpeed.get(i)).get("direction").toString()).floatValue());
+                    heFengHour.setHumidity(new BigDecimal(((JSONObject) humidityHour.get(i)).get("value").toString()).floatValue());
+                    heFengHour.setPressure(new BigDecimal(((JSONObject) pressureHour.get(i)).get("value").toString()).floatValue());
+                    heFengHour.setText(skycon(((JSONObject) skyconHour.get(i)).get("value").toString()));
+                    heFengHour.setDswrf(new BigDecimal(((JSONObject) dswrf.get(i)).get("value").toString()).floatValue());
+                    heFengHour.setTemp(new BigDecimal(((JSONObject) temperature.get(i)).get("value").toString()).floatValue());
+                    heFengHourList.add(heFengHour);
+                }
+            } else {
+                log.info("{} 的彩云小时数据不足72小时,不入库!", name);
+            }*/
+            //日数据写入
+            List<HeFengDay> heFengDayList = new ArrayList<>();
+            if (windSpeed8Day.size() == 7 && windSpeed20Day.size() == 7 && skycon8.size() == 7 && skycon20.size() == 7 && dswrfDay.size() == 7 & temperatureDay.size() == 7) {
+                for (int i = 0; i < windSpeed8Day.size(); i++) {
+                    String time = ((JSONObject) windSpeed8Day.get(i)).get("date").toString();
+                    //白天风速
+                    Map windspeedDay = (Map) ((JSONObject) windSpeed8Day.get(i)).get("avg");
+                    String windspeedDay1 = windspeedDay.get("speed").toString();
+                    //白天风向
+                    String wind360Day1 = windspeedDay.get("direction").toString();
+                    //夜间风速
+                    Map windspeedNight = (Map) ((JSONObject) windSpeed20Day.get(i)).get("avg");
+                    String windspeedNight1 = windspeedNight.get("speed").toString();
+                    String wind360Night1 = windspeedNight.get("direction").toString();
+                    //辐照度
+                    String dswrf1 = ((JSONObject) dswrfDay.get(i)).get("avg").toString();
+                    //白天天气
+                    String skycon = ((JSONObject) skycon8.get(i)).get("value").toString();
+                    //夜间天气
+                    String skyconN = ((JSONObject) skycon20.get(i)).get("value").toString();
+                    //最高温度
+                    String temperatureMax = ((JSONObject) temperatureDay.get(i)).get("max").toString();
+                    //最低温度
+                    String temperatureMin = ((JSONObject) temperatureDay.get(i)).get("min").toString();
+                    HeFengDay heFengDay = new HeFengDay();
+                    heFengDay.setTs(getTimestamp(time));
+                    heFengDay.setWindSpeedDay(new BigDecimal(windspeedDay1).floatValue());
+                    heFengDay.setWindSpeedMDay(new BigDecimal(windspeedDay1).floatValue() * 1000 / 3600);
+                    heFengDay.setWind360Day(new BigDecimal(wind360Day1).floatValue());
+                    heFengDay.setWindScaleDay(speedLevel(windspeedDay1));
+                    heFengDay.setWindSpeedNight(new BigDecimal(windspeedNight1).floatValue());
+                    heFengDay.setWindSpeedMNight(new BigDecimal(windspeedNight1).floatValue() * 1000 / 3600);
+                    heFengDay.setWind360Night(new BigDecimal(wind360Night1).floatValue());
+                    heFengDay.setWindScaleNight(speedLevel(windspeedNight1));
+                    heFengDay.setDswrf(new BigDecimal(dswrf1).floatValue());
+                    heFengDay.setTextDay(skycon(skycon));
+                    heFengDay.setTextNight(skycon(skyconN));
+                    heFengDay.setTempMax(new BigDecimal(temperatureMax).floatValue());
+                    heFengDay.setTempMin(new BigDecimal(temperatureMin).floatValue());
+                    heFengDayList.add(heFengDay);
+                }
+            } else {
+                log.info("{} 的彩云日数据不足7天,不入库!", name);
+            }
+            /*for (HeFengHour item : heFengHourList) {
+                String insertSql = " INSERT INTO hefeng_hour_unit_" + areaCode + " USING hefeng_hour_unit TAGS('" + areaCode + "') values('" + item.getTs() + "', " + item.getTemp() + ", '" + item.getText() + "', '" + item.getWindDir() + "', " + item.getWind360() + ", " + item.getWindSpeed()  + ", " + item.getWindScale() + ", " + item.getHumidity() + ", " + item.getCloud() + ", " + item.getPrecip() + ", " + item.getDew() + ", " + item.getPressure() + ", " + item.getDswrf() +", " + item.getWindSpeedM()+ ")";
+                int affectedRows = ps.executeUpdate(insertSql);
+            }*/
+            for (HeFengDay item : heFengDayList) {
+                String insertSQL = "INSERT INTO hefeng_day_unit_" + areaCode + " USING hefeng_day_unit TAGS('" + areaCode + "')  values('" + item.getTs() + "', " + item.getTempMax() + ", " + item.getTempMin() + ", '" + item.getTextDay() + "', '" + item.getTextNight() + "', " + item.getWind360Day() + ", '" + item.getWindDirDay() + "', " + item.getWindScaleDay() + ", " + item.getWindSpeedDay() + ", " + item.getWind360Night() + ", '" + item.getWindDirNight() + "', " + item.getWindScaleNight() + ", " + item.getWindSpeedNight() + ", " + item.getHumidity() + ", " + item.getPrecip() + ", " + item.getPressure() + ", " + item.getDswrf() + ", " + item.getWindSpeedMDay() + ", " + item.getWindSpeedMNight() + ")";
+                int affectedRows = ps.executeUpdate(insertSQL);
+            }
+            if (ps != null)
+                ps.close();
+        } catch (Exception e) {
+            log.error("彩云天气,地区:{} 日天气数据下载失败JSON格式化错误", name);
+            return true;
+        }
+        log.info("彩云天气,地区:{} 日天气数据下载完成", name);
+        return false;
+    }
+
+    private Timestamp getTimestamp(String time) {
+        // 解析字符串为 ZonedDateTime
+        ZonedDateTime zonedDateTime = ZonedDateTime.parse(time);
+        // 将 ZonedDateTime 转换为 Instant
+        Instant instant = zonedDateTime.toInstant();
+        // 将 Instant 转换为 Timestamp
+        return Timestamp.from(instant);
+    }
+
+    /**
+     * 根据代码获取对应天气描述
+     *
+     * @param skycon
+     * @return
+     */
+    private String skycon(String skycon) {
+        switch (skycon) {
+            case "CLEAR_DAY":
+            case "CLEAR_NIGHT":
+                return "晴";
+            case "PARTLY_CLOUDY_DAY":
+            case "PARTLY_CLOUDY_NIGHT":
+                return "多云";
+            case "CLOUDY":
+                return "阴";
+            case "LIGHT_HAZE":
+                return "轻度雾霾";
+            case "MODERATE_HAZE":
+                return "中度雾霾";
+            case "HEAVY_HAZE":
+                return "重度雾霾";
+            case "LIGHT_RAIN":
+                return "小雨";
+            case "MODERATE_RAIN":
+                return "中雨";
+            case "HEAVY_RAIN":
+                return "大雨";
+            case "STORM_RAIN":
+                return "暴雨";
+            case "FOG":
+                return "雾";
+            case "LIGHT_SNOW":
+                return "小雪";
+            case "MODERATE_SNOW":
+                return "中雪";
+            case "HEAVY_SNOW":
+                return "大雪";
+            case "STORM_SNOW":
+                return "暴雪";
+            case "DUST":
+                return "浮尘";
+            case "SAND":
+                return "沙尘";
+            case "WIND":
+                return "大风";
+        }
+        return "晴";
+    }
+
+
+}

+ 265 - 0
src/main/java/com/example/getweather/service/GetWeatherXmo.java

@@ -0,0 +1,265 @@
+package com.example.getweather.service;
+
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.db.Db;
+import cn.hutool.db.Entity;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.example.getweather.entity.DistrictCodeDO;
+import com.example.getweather.entity.HeFengHour;
+import com.example.getweather.util.WeixinPush;
+import com.taosdata.jdbc.TSDBDriver;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.Statement;
+import java.sql.Timestamp;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+@Validated
+@Slf4j
+public class GetWeatherXmo {
+    @Resource
+    private WeixinPush weixinPush;
+
+    // 辅助方法:安全地获取列表中的值并转换为字符串,如果列表为空或索引越界则返回空字符串
+    private static String getValueSafelyAsString(List<?> list, int index) {
+        if (list == null || index < 0 || index >= list.size()) {
+            return "";
+        }
+        Object value = list.get(index);
+        return value != null ? String.valueOf(value) : "";
+    }
+
+    // 辅助方法:安全地获取列表中的值,如果列表为空或索引越界则返回null
+    private static <T> T getValueSafely(List<T> list, int index) {
+        if (list == null || index < 0 || index >= list.size()) {
+            return null;
+        }
+        return list.get(index);
+    }
+
+    public void download() {
+        List<String> areaCodes = new ArrayList<>();
+        List<DistrictCodeDO> districtCodeDOList = new ArrayList<>();
+        // 获取今天的日期(yyyy-MM-dd)
+        String startDate = DateUtil.today();
+        String endDate = DateUtil.offsetDay(DateUtil.date(), 15).toString("yyyy-MM-dd");
+        boolean isApiQuotaExhausted = false; // 引入标志变量
+        try {
+            List<Entity> dictList = Db.use().findAll("system_dict_data");
+            for (Entity entity : dictList) {
+                String name = entity.getStr("label");
+                if (name.contains("area_code")) {
+                    String code = entity.getStr("value");
+                    String[] s = code.split(",");
+                    areaCodes = Arrays.asList(s);
+                }
+            }
+            List<Entity> districtCodes = Db.use().findAll("jy_district_code");
+            for (Entity e : districtCodes) {
+                DistrictCodeDO districtCodeDO = new DistrictCodeDO();
+                districtCodeDO.setCode(Integer.parseInt(e.getStr("code")));
+                districtCodeDO.setName(e.getStr("name"));
+                districtCodeDO.setLevel(Integer.parseInt(e.getStr("level")));
+                districtCodeDO.setType(Integer.parseInt(e.getStr("type")));
+                districtCodeDO.setAbname(e.getStr("abname"));
+                districtCodeDO.setPid(Integer.parseInt(e.getStr("pid")));
+                districtCodeDO.setLat(!Objects.equals(e.getStr("lat"), "") && e.getStr("lat") != null ? new BigDecimal(e.getStr("lat")).setScale(6, RoundingMode.HALF_UP).doubleValue() : 0d);
+                districtCodeDO.setLng(!Objects.equals(e.getStr("lng"), "") && e.getStr("lng") != null ? new BigDecimal(e.getStr("lng")).setScale(6, RoundingMode.HALF_UP).doubleValue() : 0d);
+                districtCodeDOList.add(districtCodeDO);
+            }
+            String jdbcUrl = "jdbc:TAOS://192.168.12.241:19500/etadm_local?user=root&password=qE$#6G0zROoc";
+            Properties connProps = new Properties();
+            connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
+            connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
+            connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
+            Connection conn = DriverManager.getConnection(jdbcUrl, connProps);
+            //省份
+            for (String code : areaCodes) {
+                if (isApiQuotaExhausted) break; // 检查标志变量
+                List<DistrictCodeDO> shiList = districtCodeDOList.stream().filter(item -> item.getPid().toString().equals(code)).collect(Collectors.toList());
+                //市
+                for (DistrictCodeDO d : shiList) {
+                    if (isApiQuotaExhausted) break; // 检查标志变量
+                    List<DistrictCodeDO> quList = districtCodeDOList.stream().filter(item -> item.getPid().toString().equals(d.getCode().toString())).collect(Collectors.toList());
+                    String xmoUrl;
+                    //曦谋综合数据查询
+                    xmoUrl = "https://weather-api.xm-opt.com/v1/forecast15Minutes?latitude=" + d.getLat() + "&longitude=" + d.getLng() + "&minutely_15=weather_code,temperature_2m,surface_pressure,relative_humidity_2m,precipitation,cloud_cover,wind_speed_10m,wind_direction_10m,shortwave_radiation&timezone=Asia%2FShanghai&start_date=" + startDate + "&end_date=" + endDate;
+                    isApiQuotaExhausted = analysis(xmoUrl, d.getCode(), d.getName(), conn); // 传递标志变量
+                    if (isApiQuotaExhausted) break; // 检查标志变量
+                    //区
+                    for (DistrictCodeDO q : quList) {
+                        if (isApiQuotaExhausted) break; // 检查标志变量
+                        xmoUrl = "https://weather-api.xm-opt.com/v1/forecast15Minutes?latitude=" + d.getLat() + "&longitude=" + d.getLng() + "&minutely_15=weather_code,temperature_2m,surface_pressure,relative_humidity_2m,precipitation,cloud_cover,wind_speed_10m,wind_direction_10m,shortwave_radiation&timezone=Asia%2FShanghai&start_date=" + startDate + "&end_date=" + endDate;
+                        isApiQuotaExhausted = analysis(xmoUrl, q.getCode(), q.getName(), conn); // 传递标志变量
+                        if (isApiQuotaExhausted) break; // 检查标志变量
+                        //线程睡5秒 防止请求过快
+                        Thread.sleep(5000);
+                    }
+                }
+            }
+            conn.close();
+            String alarm = "电力交易系统在获取曦谋天气数据时出现异常";
+            String description = "接口调用异常";
+            if (isApiQuotaExhausted) {
+                //给企业微信发送消息
+                weixinPush.sendMessageBot(alarm, description);
+            } else {
+                alarm = "电力交易系统曦谋天气数据全部下载完毕";
+                description = "接口调用成功";
+                weixinPush.sendMessageBot(alarm, description);
+                log.info("曦谋天气15分钟级天气数据全部下载完毕");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public boolean analysis(String xmoUrl, int areaCode, String name, Connection conn) {
+        log.info("曦谋天气数据,开始下载地区:{} 的天气数据", name);
+        try {
+            Statement ps = conn.createStatement();
+            String body = HttpUtil.createGet(xmoUrl).header("apikey", "c615a8f6-f5dd-4a81-86fe-db2a42862c15").execute().charset("utf-8").body();
+            //String body = HttpUtil.createGet(xmoUrl).header("apikey", "51bcabf8-3a5e-41e9-8bf2-b7676936cb22").execute().charset("utf-8").body();
+            JSONObject jsonObject = JSONUtil.parseObj(body);
+            //log.info("获取到的数据为:{}", body);
+            if (jsonObject.toString().contains("API call limit has been reached")) {
+                return true;
+            }
+            JSONObject result = JSONUtil.parseObj(jsonObject.get("minutely_15"));
+            List<HeFengHour> xmoList = new ArrayList<>();
+            // 获取各个数据数组
+            List<String> timeList = result.get("time", List.class);
+            List weatherCodeList = result.get("weather_code", List.class);
+            List temperature2mList = result.get("temperature_2m", List.class);
+            List surfacePressureList = result.get("surface_pressure", List.class);
+            List relativeHumidity2mList = result.get("relative_humidity_2m", List.class);
+            List precipitationList = result.get("precipitation", List.class);
+            List cloudCoverList = result.get("cloud_cover", List.class);
+            List windSpeed10mList = result.get("wind_speed_10m", List.class);
+            List windDirection10mList = result.get("wind_direction_10m", List.class);
+            List shortwaveRadiationList = result.get("shortwave_radiation", List.class);
+            int length = timeList == null ? 0 : timeList.size();
+            //获取当前时间 yyyy-mm-dd hh:mm
+            //String currentTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
+            // 定义输入日期时间格式
+            DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm");
+            if (length > 0) {
+                // 遍历数组,填充XMO对象并添加到列表
+                for (int i = 0; i < length; i++) {
+                    HeFengHour heFengHour = new HeFengHour();
+                    // 解析输入字符串为 LocalDateTime 对象
+                    LocalDateTime localDateTime = LocalDateTime.parse(getValueSafely(timeList, i), inputFormatter);
+                    // 将 LocalDateTime 转换为 Instant 对象
+                    Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
+                    // 将 Instant 对象转换为 Date 对象
+                    //Date 转为 timestamp。getTimestamp
+                    Date date = Date.from(instant);
+                    heFengHour.setTs(new Timestamp(date.getTime()));
+                    heFengHour.setWindSpeed(windSpeed10mList.get(i) == null ? -0.99f : new BigDecimal(windSpeed10mList.get(i).toString()).floatValue());
+                    heFengHour.setWindSpeedM(windSpeed10mList.get(i) == null ? -0.99f : new BigDecimal(windSpeed10mList.get(i).toString()).floatValue() * 1000 / 3600);
+                    heFengHour.setWind360(windDirection10mList.get(i) == null ? -0.99f : new BigDecimal(windDirection10mList.get(i).toString()).floatValue());
+                    heFengHour.setTemp(temperature2mList.get(i) == null ? -0.99f : new BigDecimal(temperature2mList.get(i).toString()).floatValue());
+                    heFengHour.setPrecip(precipitationList.get(i) == null ? -0.99f : new BigDecimal(precipitationList.get(i).toString()).floatValue());
+                    heFengHour.setText(skycon(weatherCodeList.get(i) == null ? "0" : weatherCodeList.get(i).toString()));
+                    heFengHour.setDswrf(shortwaveRadiationList.get(i) == null ? -0.99f : new BigDecimal(shortwaveRadiationList.get(i).toString()).floatValue());
+                    heFengHour.setHumidity(relativeHumidity2mList.get(i) == null ? -0.99f : new BigDecimal(relativeHumidity2mList.get(i).toString()).floatValue());
+                    heFengHour.setPressure(surfacePressureList.get(i) == null ? -0.99f : new BigDecimal(surfacePressureList.get(i).toString()).floatValue());
+                    heFengHour.setCloud(cloudCoverList.get(i) == null ? -0.99f : new BigDecimal(cloudCoverList.get(i).toString()).floatValue());
+                    xmoList.add(heFengHour);
+                }
+            }
+            for (HeFengHour item : xmoList) {
+                String insertSql = " INSERT INTO hefeng_hour_unit_" + areaCode + " USING hefeng_hour_unit TAGS('" + areaCode + "') values('" + item.getTs() + "', " + item.getTemp() + ", '" + item.getText() + "', '" + item.getWindDir() + "', " + item.getWind360() + ", " + item.getWindSpeed() + ", " + item.getWindScale() + ", " + item.getHumidity() + ", " + item.getCloud() + ", " + item.getPrecip() + ", " + item.getDew() + ", " + item.getPressure() + ", " + item.getDswrf() + ", " + item.getWindSpeedM() + ")";
+                int affectedRows = ps.executeUpdate(insertSql);
+            }
+            log.info("曦谋天气,地区:{} 15分钟级天气数据下载完成. 数据条数:{}", name, xmoList.size());
+            if (ps != null)
+                ps.close();
+        } catch (Exception e) {
+            log.error("曦谋天气,地区:{}  15分钟级天气数据下载失败JSON格式化错误" + e, name);
+            e.printStackTrace();
+            return true;
+        }
+        return false;
+    }
+
+
+    /**
+     * 根据代码获取对应天气描述
+     *
+     * @param skycon
+     * @return
+     */
+    private String skycon(String skycon) {
+        switch (skycon) {
+            case "0":
+                return "晴";
+            case "1":
+                return "多云";
+            case "2":
+                return "少云";
+            case "3":
+                return "阴";
+            case "45":
+                return "雾";
+            case "48":
+                return "冻雾";
+            case "51":
+            case "53":
+            case "55":
+                return "毛毛雨";
+            case "56":
+            case "57":
+                return "冻毛毛雨";
+            case "61":
+                return "小雨";
+            case "63":
+                return "中雨";
+            case "65":
+                return "大雨";
+            case "66":
+            case "67":
+                return "冻雨";
+            case "71":
+                return "小雪";
+            case "73":
+                return "中雪";
+            case "75":
+                return "大雪";
+            case "77":
+                return "雪粒";
+            case "80":
+                return "小阵雨";
+            case "81":
+                return "阵雨";
+            case "82":
+                return "强阵雨";
+            case "85":
+                return "小阵雪";
+            case "86":
+                return "阵雪";
+            case "95":
+                return "雷雨";
+            case "96":
+            case "99":
+                return "雷雨伴有冰雹";
+            default:
+                return "晴"; // 默认返回晴
+        }
+    }
+}

+ 341 - 0
src/main/java/com/example/getweather/service/XmoComplements.java

@@ -0,0 +1,341 @@
+package com.example.getweather.service;
+
+import cn.hutool.db.Db;
+import cn.hutool.db.Entity;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.example.getweather.entity.DistrictCodeDO;
+import com.example.getweather.entity.HeFengDay;
+import com.example.getweather.entity.HeFengHour;
+import com.example.getweather.util.WeixinPush;
+import com.taosdata.jdbc.TSDBDriver;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.sql.*;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.Date;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+@Validated
+@Slf4j
+public class XmoComplements {
+    @Resource
+    private WeixinPush weixinPush;
+
+    // 辅助方法:安全地获取列表中的值并转换为字符串,如果列表为空或索引越界则返回空字符串
+    private static String getValueSafelyAsString(List<?> list, int index) {
+        if (list == null || index < 0 || index >= list.size()) {
+            return "";
+        }
+        Object value = list.get(index);
+        return value != null ? String.valueOf(value) : "";
+    }
+
+    // 辅助方法:安全地获取列表中的值,如果列表为空或索引越界则返回null
+    private static <T> T getValueSafely(List<T> list, int index) {
+        if (list == null || index < 0 || index >= list.size()) {
+            return null;
+        }
+        return list.get(index);
+    }
+
+    public static Timestamp convertToTimestamp(String dateTimeStr) {
+        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        try {
+            Date parsedDate = dateFormat.parse(dateTimeStr);
+            return new Timestamp(parsedDate.getTime());
+        } catch (ParseException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    public void download() {
+        List<String> areaCodes = new ArrayList<>();
+        List<DistrictCodeDO> districtCodeDOList = new ArrayList<>();
+        // 获取今天的日期(yyyy-MM-dd)
+        String startDate = "2025-02-18";
+        String endDate = "2025-03-05";
+        boolean isApiQuotaExhausted = false; // 引入标志变量
+        try {
+            List<Entity> dictList = Db.use().findAll("system_dict_data");
+            for (Entity entity : dictList) {
+                String name = entity.getStr("label");
+                if (name.contains("area_code")) {
+                    String code = entity.getStr("value");
+                    String[] s = code.split(",");
+                    areaCodes = Arrays.asList(s);
+                }
+            }
+            List<Entity> districtCodes = Db.use().findAll("jy_district_code");
+            for (Entity e : districtCodes) {
+                DistrictCodeDO districtCodeDO = new DistrictCodeDO();
+                districtCodeDO.setCode(Integer.parseInt(e.getStr("code")));
+                districtCodeDO.setName(e.getStr("name"));
+                districtCodeDO.setLevel(Integer.parseInt(e.getStr("level")));
+                districtCodeDO.setType(Integer.parseInt(e.getStr("type")));
+                districtCodeDO.setAbname(e.getStr("abname"));
+                districtCodeDO.setPid(Integer.parseInt(e.getStr("pid")));
+                districtCodeDO.setLat(!Objects.equals(e.getStr("lat"), "") && e.getStr("lat") != null ? new BigDecimal(e.getStr("lat")).setScale(6, RoundingMode.HALF_UP).doubleValue() : 0d);
+                districtCodeDO.setLng(!Objects.equals(e.getStr("lng"), "") && e.getStr("lng") != null ? new BigDecimal(e.getStr("lng")).setScale(6, RoundingMode.HALF_UP).doubleValue() : 0d);
+                districtCodeDOList.add(districtCodeDO);
+            }
+            String jdbcUrl = "jdbc:TAOS://192.168.12.241:19500/etadm_local?user=root&password=qE$#6G0zROoc";
+            Properties connProps = new Properties();
+            connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
+            connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
+            connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
+            Connection conn = DriverManager.getConnection(jdbcUrl, connProps);
+            //省份
+            for (String code : areaCodes) {
+                if (isApiQuotaExhausted) break; // 检查标志变量
+                List<DistrictCodeDO> shiList = districtCodeDOList.stream().filter(item -> item.getPid().toString().equals(code)).collect(Collectors.toList());
+                //市
+                for (DistrictCodeDO d : shiList) {
+                    if (isApiQuotaExhausted) break; // 检查标志变量
+                    List<DistrictCodeDO> quList = districtCodeDOList.stream().filter(item -> item.getPid().toString().equals(d.getCode().toString())).collect(Collectors.toList());
+                    String xmoUrl;
+                    //曦谋综合数据查询
+                    xmoUrl = "https://weather-api.xm-opt.com/v1/forecast15Minutes?latitude=" + d.getLat() + "&longitude=" + d.getLng() + "&minutely_15=weather_code,temperature_2m,surface_pressure,relative_humidity_2m,precipitation,cloud_cover,wind_speed_10m,wind_direction_10m,shortwave_radiation&timezone=Asia%2FShanghai&start_date=" + startDate + "&end_date=" + endDate;
+                    isApiQuotaExhausted = analysis(xmoUrl, d.getCode(), d.getName(), conn); // 传递标志变量
+                    if (isApiQuotaExhausted) break; // 检查标志变量
+                    //区
+                    for (DistrictCodeDO q : quList) {
+                        if (isApiQuotaExhausted) break; // 检查标志变量
+                        xmoUrl = "https://weather-api.xm-opt.com/v1/forecast15Minutes?latitude=" + d.getLat() + "&longitude=" + d.getLng() + "&minutely_15=weather_code,temperature_2m,surface_pressure,relative_humidity_2m,precipitation,cloud_cover,wind_speed_10m,wind_direction_10m,shortwave_radiation&timezone=Asia%2FShanghai&start_date=" + startDate + "&end_date=" + endDate;
+                        isApiQuotaExhausted = analysis(xmoUrl, q.getCode(), q.getName(), conn); // 传递标志变量
+                        if (isApiQuotaExhausted) break; // 检查标志变量
+                        //线程睡5秒 防止请求过快
+                        Thread.sleep(5000);
+                    }
+                }
+            }
+            conn.close();
+            String alarm = "电力交易系统在获取15分钟级天气数据时报错, 曦谋天气API 额度已用尽";
+            String description = "接口调用异常";
+            if (isApiQuotaExhausted) {
+                //给企业微信发送消息
+                //weixinPush.sendMessageBot(alarm, description);
+            } else {
+                alarm = "电力交易系统曦谋天气数据全部下载完毕";
+                description = "接口调用成功";
+                //weixinPush.sendMessageBot(alarm, description);
+                log.info("曦谋天气15分钟级天气数据全部下载完毕");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public boolean analysis(String xmoUrl, int areaCode, String name, Connection conn) {
+        log.info("曦谋天气数据,开始下载地区:{} 的天气数据", name);
+        try {
+            Statement ps = conn.createStatement();
+            String body = HttpUtil.createGet(xmoUrl).header("apikey", "c615a8f6-f5dd-4a81-86fe-db2a42862c15").execute().charset("utf-8").body();
+            JSONObject jsonObject = JSONUtil.parseObj(body);
+            if (jsonObject.toString().contains("API call limit has been reached")) {
+                return true;
+            }
+            JSONObject result = JSONUtil.parseObj(jsonObject.get("minutely_15"));
+            List<HeFengHour> xmoList = new ArrayList<>();
+            // 获取各个数据数组
+            List<String> timeList = result.get("time", List.class);
+            List<Integer> weatherCodeList = result.get("weather_code", List.class);
+            List<Double> temperature2mList = result.get("temperature_2m", List.class);
+            List<Double> surfacePressureList = result.get("surface_pressure", List.class);
+            List<Double> relativeHumidity2mList = result.get("relative_humidity_2m", List.class);
+            List<Double> precipitationList = result.get("precipitation", List.class);
+            List<Double> cloudCoverList = result.get("cloud_cover", List.class);
+            List<Double> windSpeed10mList = result.get("wind_speed_10m", List.class);
+            List<Double> windDirection10mList = result.get("wind_direction_10m", List.class);
+            List<Double> shortwaveRadiationList = result.get("shortwave_radiation", List.class);
+            int length = timeList == null ? 0 : timeList.size();
+            //获取当前时间 yyyy-mm-dd hh:mm
+            //String currentTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
+            // 定义输入日期时间格式
+            DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm");
+            if (length > 0) {
+                // 遍历数组,填充XMO对象并添加到列表
+                for (int i = 0; i < length; i++) {
+                    HeFengHour heFengHour = new HeFengHour();
+                    // 解析输入字符串为 LocalDateTime 对象
+                    LocalDateTime localDateTime = LocalDateTime.parse(getValueSafely(timeList, i), inputFormatter);
+                    // 将 LocalDateTime 转换为 Instant 对象
+                    Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
+                    // 将 Instant 对象转换为 Date 对象
+                    //Date 转为 timestamp。getTimestamp
+                    Date date = Date.from(instant);
+                    heFengHour.setTs(new Timestamp(date.getTime()));
+                    heFengHour.setWindSpeed(Objects.equals(getValueSafelyAsString(windSpeed10mList, i), "") || getValueSafelyAsString(windSpeed10mList, i) == null ? null : Float.parseFloat(getValueSafelyAsString(windSpeed10mList, i)));
+                    heFengHour.setWindSpeedM(Objects.equals(getValueSafelyAsString(windSpeed10mList, i), "") || getValueSafelyAsString(windSpeed10mList, i) == null ? null : Float.parseFloat(getValueSafelyAsString(windSpeed10mList, i)) * 1000 / 3600);
+                    heFengHour.setWindDir(getValueSafelyAsString(windDirection10mList, i));
+                    heFengHour.setTemp(Objects.equals(getValueSafelyAsString(temperature2mList, i), "") || getValueSafelyAsString(temperature2mList, i) == null ? null : Float.parseFloat(getValueSafelyAsString(temperature2mList, i)));
+                    heFengHour.setPrecip(Float.parseFloat(getValueSafelyAsString(precipitationList, i)));
+                    heFengHour.setText(skycon(getValueSafelyAsString(weatherCodeList, i)));
+                    heFengHour.setDswrf(Float.parseFloat(getValueSafelyAsString(shortwaveRadiationList, i)));
+                    heFengHour.setHumidity(Objects.equals(getValueSafelyAsString(relativeHumidity2mList, i), "") || getValueSafelyAsString(relativeHumidity2mList, i) == null ? null : Float.parseFloat(getValueSafelyAsString(relativeHumidity2mList, i)));
+                    heFengHour.setPressure(Objects.equals(getValueSafelyAsString(surfacePressureList, i), "") || getValueSafelyAsString(surfacePressureList, i) == null ? null : Float.parseFloat(getValueSafelyAsString(surfacePressureList, i)));
+                    heFengHour.setCloud(Objects.equals(getValueSafelyAsString(cloudCoverList, i), "") || getValueSafelyAsString(cloudCoverList, i) == null ? null : Float.parseFloat(getValueSafelyAsString(cloudCoverList, i)));
+                    xmoList.add(heFengHour);
+                }
+            }
+            for (HeFengHour item : xmoList) {
+                String insertSql = " INSERT INTO hefeng_hour_unit_" + areaCode + " USING hefeng_hour_unit TAGS('" + areaCode + "') values('" + item.getTs() + "', " + item.getTemp() + ", '" + item.getText() + "', '" + item.getWindDir() + "', " + item.getWind360() + ", " + item.getWindSpeed() + ", " + item.getWindScale() + ", " + item.getHumidity() + ", " + item.getCloud() + ", " + item.getPrecip() + ", " + item.getDew() + ", " + item.getPressure() + ", " + item.getDswrf() + ", " + item.getWindSpeedM() + ")";
+                int affectedRows = ps.executeUpdate(insertSql);
+            }
+            if (ps != null)
+                ps.close();
+        } catch (Exception e) {
+            log.error("曦谋天气,地区:{}  15分钟级天气数据下载失败JSON格式化错误" + e, name);
+            return true;
+        }
+        log.info("曦谋天气,地区:{} 15分钟级天气数据下载完成", name);
+        return false;
+    }
+
+    /**
+     * 根据代码获取对应天气描述
+     *
+     * @param skycon
+     * @return
+     */
+    private String skycon(String skycon) {
+        switch (skycon) {
+            case "0":
+                return "晴";
+            case "1":
+                return "多云";
+            case "2":
+                return "少云";
+            case "3":
+                return "阴";
+            case "45":
+                return "雾";
+            case "48":
+                return "冻雾";
+            case "51":
+            case "53":
+            case "55":
+                return "毛毛雨";
+            case "56":
+            case "57":
+                return "冻毛毛雨";
+            case "61":
+                return "小雨";
+            case "63":
+                return "中雨";
+            case "65":
+                return "大雨";
+            case "66":
+            case "67":
+                return "冻雨";
+            case "71":
+                return "小雪";
+            case "73":
+                return "中雪";
+            case "75":
+                return "大雪";
+            case "77":
+                return "雪粒";
+            case "80":
+                return "小阵雨";
+            case "81":
+                return "阵雨";
+            case "82":
+                return "强阵雨";
+            case "85":
+                return "小阵雪";
+            case "86":
+                return "阵雪";
+            case "95":
+                return "雷雨";
+            case "96":
+            case "99":
+                return "雷雨伴有冰雹";
+            default:
+                return "晴"; // 默认返回晴
+        }
+    }
+
+    public void cal() {
+
+        try {
+            String jdbcUrl = "jdbc:TAOS://192.168.12.241:19500/etadm_local?user=root&password=qE$#6G0zROoc";
+            Properties connProps = new Properties();
+            connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
+            connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
+            connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
+            Connection conn = DriverManager.getConnection(jdbcUrl, connProps);
+            //--------------------------------------------------
+            Statement ps;
+            ps = conn.createStatement();
+            //所有数据
+            ResultSet rs = null;
+            //转换过后的数据
+            List<Map<String, String>> a;
+            String start = "";
+            String end = "";
+            //---------创建文件----------
+            //String[] csvNames = table.split(",");
+            String sql = "select * from etadm_local.hefeng_day_unit";
+            rs = ps.executeQuery(sql);
+            //计数
+            int count = 0;
+            List<HeFengDay> hefengDayList = new ArrayList<>();
+            while (rs.next()) {
+                HeFengDay heFengDay = new HeFengDay();
+                heFengDay.setAreaCode(rs.getString("area_code"));
+                heFengDay.setTs(convertToTimestamp(rs.getString("ts")));
+                heFengDay.setTempMax(Float.parseFloat(rs.getString("temp_max")));
+                heFengDay.setTempMin(Float.parseFloat(rs.getString("temp_min")));
+                heFengDay.setTextDay(rs.getString("text_day"));
+                heFengDay.setTextNight(rs.getString("text_night"));
+                heFengDay.setWind360Day(Float.parseFloat(rs.getString("wind_360_day")));
+                heFengDay.setWindDirDay(rs.getString("wind_dir_day"));
+                heFengDay.setWindScaleDay(new BigDecimal(rs.getString("wind_scale_day")).intValue());
+                heFengDay.setWindSpeedDay(Float.parseFloat(rs.getString("wind_speed_day")));
+                heFengDay.setWind360Night(Float.parseFloat(rs.getString("wind_360_night")));
+                heFengDay.setWindDirNight(rs.getString("wind_dir_night"));
+                heFengDay.setWindScaleNight(new BigDecimal(rs.getString("wind_scale_night")).intValue());
+                heFengDay.setWindSpeedNight(Float.parseFloat(rs.getString("wind_speed_night")));
+                heFengDay.setHumidity(Float.parseFloat(rs.getString("humidity")));
+                heFengDay.setPrecip(Float.parseFloat(rs.getString("precip")));
+                heFengDay.setPressure(Float.parseFloat(rs.getString("pressure")));
+                heFengDay.setDswrf(Float.parseFloat(rs.getString("dswrf")));
+                heFengDay.setWindSpeedMDay(new BigDecimal(rs.getString("wind_speed_day")).divide(BigDecimal.valueOf(3.6), 4, RoundingMode.HALF_UP).floatValue());
+                heFengDay.setWindSpeedMNight(new BigDecimal(rs.getString("wind_speed_night")).divide(BigDecimal.valueOf(3.6), 4, RoundingMode.HALF_UP).floatValue());
+                hefengDayList.add(heFengDay);
+            }
+
+            for (HeFengDay heFengDay : hefengDayList) {
+                String insertSQL = "INSERT INTO etadm_local.hefeng_day_unit_" + heFengDay.getAreaCode() + " USING hefeng_day_unit TAGS('" + heFengDay.getAreaCode() + "')  values('" + heFengDay.getTs() + "', " + heFengDay.getTempMax() + ", " + heFengDay.getTempMin() + ", '" + heFengDay.getTextDay() + "', '" + heFengDay.getTextNight() + "', " + heFengDay.getWind360Day() + ", '"
+                        + heFengDay.getWindDirDay() + "', " + heFengDay.getWindScaleDay() + ", " + heFengDay.getWindSpeedDay() + ", " + heFengDay.getWind360Night() + ", '" + heFengDay.getWindDirNight() + "', " + heFengDay.getWindScaleNight() + ", " + heFengDay.getWindSpeedNight() + ", " + heFengDay.getHumidity() + ", " + heFengDay.getPrecip() + ", "
+                        + heFengDay.getPressure() + ", " + heFengDay.getDswrf() + ", " + heFengDay.getWindSpeedMDay() + ", " + heFengDay.getWindSpeedMNight() + ")";
+                int affectedRows = ps.executeUpdate(insertSQL);
+                count = count + affectedRows;
+            }
+            log.info("数据转换完成,共转换{}条数据", count);
+            if (rs != null)
+                rs.close();
+            if (ps != null)
+                ps.close();
+            conn.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+}

+ 58 - 0
src/main/java/com/example/getweather/util/WeixinMessage.java

@@ -0,0 +1,58 @@
+package com.example.getweather.util;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.Data;
+
+@Data
+public class WeixinMessage {
+    private String toUser;
+    private String msgType;
+    private String content;
+    private String markdown;
+    private int agentid;
+
+    public String getToUser() {
+        return toUser;
+    }
+
+    public void setToUser(String toUser) {
+        this.toUser = toUser;
+    }
+
+    public String getMsgType() {
+        return msgType;
+    }
+
+    public void setMsgType(String msgType) {
+        this.msgType = msgType;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public int getAgentid() {
+        return agentid;
+    }
+
+    public void setAgentid(int agentid) {
+        this.agentid = agentid;
+    }
+
+    public String toJson() {
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("touser", toUser);
+        jsonObject.put("msgtype", msgType);
+        jsonObject.put("agentid", agentid);
+
+        JSONObject textObject = new JSONObject();
+        textObject.put("content", content);
+        jsonObject.put("text", textObject);
+
+        return jsonObject.toJSONString();
+    }
+}

+ 117 - 0
src/main/java/com/example/getweather/util/WeixinPush.java

@@ -0,0 +1,117 @@
+package com.example.getweather.util;
+
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.springframework.stereotype.Service;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+
+@Service
+public class WeixinPush {
+    private static final String CORP_ID = "ww4248d74a47dc9aef";
+    private static final String SECRET = "rN0Nf7VIHZLO-nHNRvjJ_yAwiNfbEHED8t6Z8UcR0FU";
+    private static final String ACCESS_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
+    private static final String SEND_MESSAGE_URL = "https://qyapi.weixin.qq.com/cgi-bin/message/send";
+
+    public static void main(String[] args) throws Exception {
+        WeixinPush weixinPush = new WeixinPush();
+        //WeixinMessage weixinMessage = new WeixinMessage();
+        // weixinMessage.setToUser("WangHongChen|XiuWei|DouZhi");
+        //weixinMessage.setContent(DateUtil.today() + "日 电力交易系统在获取天气数据时报错, 彩云天气API 额度已用尽");
+        //weixinMessage.setMsgType("markdown");
+        //weixinMessage.setAgentid(1000009); // 确保 agentid 正确
+
+        String alarm = "电力交易系统在获取天气数据时报错, 彩云天气API 额度已用尽";
+        String description = "接口调用异常";
+
+
+        weixinPush.sendMessageBot(alarm, description);
+    }
+
+    public String getAccessToken() throws Exception {
+        String url = ACCESS_TOKEN_URL + "?corpid=" + CORP_ID + "&corpsecret=" + SECRET;
+        HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
+        connection.setRequestMethod("GET");
+
+        BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
+        StringBuilder response = new StringBuilder();
+        String line;
+        while ((line = reader.readLine()) != null) {
+            response.append(line);
+        }
+        reader.close();
+
+        // Parse the access_token value from response
+        String token = JSON.parseObject(response.toString()).getString("access_token");
+        return token;
+    }
+
+    public void sendMessage(WeixinMessage message) throws Exception {
+        String accessToken = getAccessToken();
+
+        String url = SEND_MESSAGE_URL + "?access_token=" + accessToken;
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+        HttpPost post = new HttpPost(url);
+        post.setHeader("Content-Type", "application/json; charset=UTF-8"); // 指定字符编码
+
+        StringEntity entity = new StringEntity(message.toJson(), "UTF-8"); // 指定字符编码
+        post.setEntity(entity);
+
+        String response = EntityUtils.toString(httpClient.execute(post).getEntity(), "UTF-8"); // 指定字符编码
+        System.out.println("已将消息发送到企业微信: " + response);
+        httpClient.close();
+    }
+
+    public void sendMessageBot(String alarm, String description) throws Exception {
+        // 消息模板
+        String msgTemp = "电力交易系统气象数据接入提醒:\n" +
+                "<font color=\"comment\">{}</font>\n" +
+                "{}" +
+                "\n" +
+                "抄送:{} \n";
+        // 内容模板
+        String substanceTemp = "    ><font color=\"warning\">{}</font> \n" +
+                "事件描述:<font color=\"warning\">{}</font> \n" +
+                "{}";
+        String http = "[彩云开放平台](https://platform.caiyunapp.com/login?redirect=/dashboard/index)";
+        //String alarm = "电力交易系统在获取天气数据时报错, 彩云天气API 额度已用尽";
+        //String description = "接口调用异常";
+        String sb = StrUtil.format(substanceTemp, alarm, description, http);
+
+        StringBuilder ccp = new StringBuilder();
+        ccp.append("<@WangHongChen> ");
+        ccp.append("<@XiuWei> ");
+        ccp.append("<@DouZhi> ");
+        String content = StrUtil.format(msgTemp, DateUtil.today(), sb, ccp);
+        JSONObject markdown = new JSONObject();
+        markdown.put("content", content);
+        JSONObject reqBody = new JSONObject();
+        reqBody.put("msgtype", "markdown");
+        reqBody.put("markdown", markdown);
+        reqBody.put("safe", 0);
+
+
+        String url = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=bb68a074-8600-4891-b944-cc993e3cf158&debug=1";
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+        HttpPost post = new HttpPost(url);
+        post.setHeader("Content-Type", "application/json; charset=UTF-8"); // 指定字符编码
+
+        StringEntity entity = new StringEntity(reqBody.toJSONString(), "UTF-8"); // 指定字符编码
+        post.setEntity(entity);
+
+        String response = EntityUtils.toString(httpClient.execute(post).getEntity(), "UTF-8"); // 指定字符编码
+        System.out.println("已将消息发送到企业微信机器人: " + response);
+        httpClient.close();
+    }
+}

+ 2 - 0
src/main/resources/application.yml

@@ -0,0 +1,2 @@
+server:
+  port: 19530

+ 40 - 0
src/main/resources/db.setting

@@ -0,0 +1,40 @@
+## db.setting文件
+url = jdbc:mysql://192.168.12.20:33306/etadm-local
+user = root
+pass = mysql_G3nWZC
+## 可选配置
+# 是否在日志中显示执行的SQL
+showSql = true
+# 是否格式化显示的SQL
+formatSql = false
+# 是否显示SQL参数
+showParams = true
+
+#----------------------------------------------------------------------------------------------------------------
+## 连接池配置项
+
+## ---------------------------------------------------- Druid
+# 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时
+initialSize = 1
+# 最大连接池数量
+maxActive = 8
+# 最小连接池数量
+minIdle = 0
+# 获取连接时最大等待时间,单位毫秒。配置了maxWait之后, 缺省启用公平锁,并发效率会有所下降, 如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
+maxWait = 0
+# 是否缓存preparedStatement,也就是PSCache。 PSCache对支持游标的数据库性能提升巨大,比如说oracle。 在mysql5.5以下的版本中没有PSCache功能,建议关闭掉。作者在5.5版本中使用PSCache,通过监控界面发现PSCache有缓存命中率记录, 该应该是支持PSCache。
+poolPreparedStatements = false
+# 要启用PSCache,必须配置大于0,当大于0时, poolPreparedStatements自动触发修改为true。 在Druid中,不会存在Oracle下PSCache占用内存过多的问题, 可以把这个数值配置大一些,比如说100
+maxOpenPreparedStatements = -1
+# 用来检测连接是否有效的sql,要求是一个查询语句。 如果validationQuery为null,testOnBorrow、testOnReturn、 testWhileIdle都不会其作用。
+validationQuery = SELECT 1
+# 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
+testOnBorrow = true
+# 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
+testOnReturn = false
+# 建议配置为true,不影响性能,并且保证安全性。 申请连接的时候检测,如果空闲时间大于 timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
+testWhileIdle = false
+# 有两个含义: 1) Destroy线程会检测连接的间隔时间 2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明
+timeBetweenEvictionRunsMillis = 60000
+# 物理连接初始化的时候执行的sql
+connectionInitSqls = SELECT 1

+ 64 - 0
src/main/resources/logback.xml

@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 这个是根配置文件,一定要有的
+    scan:
+        是当配置文件被修改后会被重新加载
+    scanPeriod:
+        设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,
+        默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
+    debug:
+        当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。
+        默认值为false。
+     -->
+<configuration>
+    <!-- 日志存放路径
+        下面的标签可以自己定义
+        name:相当于Map的key
+        value:就是map的value
+        ${catalina.base}是tomcat的当前路径
+        /logs:就是tomcat下的日志路径,
+        /ehrlog:如果没有目录会默认创建
+    -->
+    <property name="LOG_HOME" value="./logs/"/>
+    <!-- appender:
+        name相当于一个名称
+        class:确定要加载哪个类
+        encoder:一定要加 encoder,
+        默认配置为PatternLayoutEncoder
+        patter:必填
+        ConsoleAppender:输出在控制台上
+    -->
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度,%msg:日志消息,%n是换行符-->
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{50}) - %highlight(%msg%n)
+            </pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+    </appender>
+    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 当前日志文件 -->
+        <file>${LOG_HOME}getWeather.log</file>
+        <!-- 编码 -->
+        <!--<Encoding>UTF-8</Encoding>-->
+        <!-- 按照时间来 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <!--日志文件输出的文件名-->
+            <FileNamePattern>${LOG_HOME}getWeather.%d{yyyy-MM-dd}.%i.log.gz</FileNamePattern>
+            <!--日志文件保留天数-->
+            <MaxHistory>180</MaxHistory>
+            <maxFileSize>10MB</maxFileSize>
+            <totalSizeCap>1024MB</totalSizeCap>
+            <cleanHistoryOnStart>true</cleanHistoryOnStart>
+        </rollingPolicy>
+        <!-- 布局 -->
+        <encoder>
+            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度,%msg:日志消息,%n是换行符-->
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+        </encoder>
+        <append>false</append>
+    </appender>
+    <root level="info">
+        <appender-ref ref="STDOUT"/>
+        <appender-ref ref="FILE"/>
+    </root>
+</configuration>

+ 13 - 0
src/test/java/com/example/getweather/GetWeatherApplicationTests.java

@@ -0,0 +1,13 @@
+package com.example.getweather;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class GetWeatherApplicationTests {
+
+    @Test
+    void contextLoads() {
+    }
+
+}