|
@@ -1,36 +1,68 @@
|
|
|
package com.usky.cdi.service.util;
|
|
package com.usky.cdi.service.util;
|
|
|
|
|
|
|
|
|
|
+import java.util.HashMap;
|
|
|
|
|
+import java.util.Map;
|
|
|
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
|
import java.io.BufferedReader;
|
|
import java.io.BufferedReader;
|
|
|
import java.io.InputStreamReader;
|
|
import java.io.InputStreamReader;
|
|
|
import java.net.HttpURLConnection;
|
|
import java.net.HttpURLConnection;
|
|
|
import java.net.URL;
|
|
import java.net.URL;
|
|
|
-import java.util.HashMap;
|
|
|
|
|
-import java.util.Map;
|
|
|
|
|
-
|
|
|
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
import org.json.JSONObject;
|
|
import org.json.JSONObject;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- *
|
|
|
|
|
|
|
+ * 天气数据获取工具类
|
|
|
|
|
+ * 使用OpenWeatherMap API获取天气数据,并进行缓存
|
|
|
* @author fyc
|
|
* @author fyc
|
|
|
* @email yuchuan.fu@chinausky.com
|
|
* @email yuchuan.fu@chinausky.com
|
|
|
* @date 2025/12/15
|
|
* @date 2025/12/15
|
|
|
*/
|
|
*/
|
|
|
-
|
|
|
|
|
|
|
+@Slf4j
|
|
|
public class WeatherFetcher {
|
|
public class WeatherFetcher {
|
|
|
private static final String API_KEY = "d04f0f84421a99b9b66dd99243c36db4";
|
|
private static final String API_KEY = "d04f0f84421a99b9b66dd99243c36db4";
|
|
|
private static final String CITY_NAME = "shanghai,cn";
|
|
private static final String CITY_NAME = "shanghai,cn";
|
|
|
private static final String API_URL = "https://api.openweathermap.org/data/2.5/weather?q=" + CITY_NAME + "&appid=" + API_KEY;
|
|
private static final String API_URL = "https://api.openweathermap.org/data/2.5/weather?q=" + CITY_NAME + "&appid=" + API_KEY;
|
|
|
|
|
|
|
|
|
|
+ // 缓存相关字段
|
|
|
|
|
+ private static final Map<String, Double> weatherCache = new ConcurrentHashMap<>();
|
|
|
|
|
+ private static long lastUpdateTime = 0;
|
|
|
|
|
+ private static final long CACHE_EXPIRE_TIME = 30 * 60 * 1000; // 缓存30分钟
|
|
|
|
|
+
|
|
|
|
|
+ // 默认天气数据,当API调用失败时使用
|
|
|
|
|
+ private static final double DEFAULT_TEMPERATURE = 15.0;
|
|
|
|
|
+ private static final int DEFAULT_HUMIDITY = 40;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取天气数据
|
|
|
|
|
+ * 1. 优先使用缓存数据(如果缓存有效)
|
|
|
|
|
+ * 2. 缓存无效时,调用API获取新数据
|
|
|
|
|
+ * 3. API调用失败时,使用默认值
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return 包含温度和湿度的Map
|
|
|
|
|
+ */
|
|
|
public static Map<String, Double> fetchWeather() {
|
|
public static Map<String, Double> fetchWeather() {
|
|
|
- double tempCelsius = 0.0;
|
|
|
|
|
- int humidity = 0;
|
|
|
|
|
|
|
+ // 1. 检查缓存是否有效
|
|
|
|
|
+ long currentTime = System.currentTimeMillis();
|
|
|
|
|
+ if (!weatherCache.isEmpty() && (currentTime - lastUpdateTime) < CACHE_EXPIRE_TIME) {
|
|
|
|
|
+ log.debug("使用缓存的天气数据,温度:{}°C,湿度:{}%",
|
|
|
|
|
+ weatherCache.get("temperature"), weatherCache.get("humidity"));
|
|
|
|
|
+ return new HashMap<>(weatherCache);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ double tempCelsius = DEFAULT_TEMPERATURE;
|
|
|
|
|
+ int humidity = DEFAULT_HUMIDITY;
|
|
|
|
|
+
|
|
|
try {
|
|
try {
|
|
|
|
|
+ log.debug("开始调用OpenWeatherMap API获取天气数据");
|
|
|
|
|
+
|
|
|
// 1. 构造请求URL
|
|
// 1. 构造请求URL
|
|
|
URL url = new URL(API_URL);
|
|
URL url = new URL(API_URL);
|
|
|
|
|
|
|
|
// 2. 建立连接并发送请求
|
|
// 2. 建立连接并发送请求
|
|
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
|
|
conn.setRequestMethod("GET");
|
|
conn.setRequestMethod("GET");
|
|
|
|
|
+ conn.setConnectTimeout(5000); // 连接超时:5秒
|
|
|
|
|
+ conn.setReadTimeout(5000); // 读取超时:5秒
|
|
|
|
|
|
|
|
// 3. 读取响应
|
|
// 3. 读取响应
|
|
|
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
|
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
|
@@ -41,11 +73,11 @@ public class WeatherFetcher {
|
|
|
}
|
|
}
|
|
|
reader.close();
|
|
reader.close();
|
|
|
|
|
|
|
|
- // 4. 解析JSON数据(这里使用了org.json库)
|
|
|
|
|
|
|
+ // 4. 解析JSON数据(使用org.json库)
|
|
|
JSONObject jsonResponse = new JSONObject(response.toString());
|
|
JSONObject jsonResponse = new JSONObject(response.toString());
|
|
|
JSONObject main = jsonResponse.getJSONObject("main");
|
|
JSONObject main = jsonResponse.getJSONObject("main");
|
|
|
|
|
|
|
|
- // 1. 提取基础信息
|
|
|
|
|
|
|
+ // 提取基础信息
|
|
|
String cityName = jsonResponse.getString("name");
|
|
String cityName = jsonResponse.getString("name");
|
|
|
int timezoneOffset = jsonResponse.getInt("timezone");
|
|
int timezoneOffset = jsonResponse.getInt("timezone");
|
|
|
|
|
|
|
@@ -56,30 +88,39 @@ public class WeatherFetcher {
|
|
|
double feelsLikeKelvin = main.getDouble("feels_like");
|
|
double feelsLikeKelvin = main.getDouble("feels_like");
|
|
|
double feelsLikeCelsius = feelsLikeKelvin - 273.15;
|
|
double feelsLikeCelsius = feelsLikeKelvin - 273.15;
|
|
|
|
|
|
|
|
- // 3. 提取天气状况描述
|
|
|
|
|
|
|
+ // 提取天气状况描述
|
|
|
JSONObject weather = jsonResponse.getJSONArray("weather").getJSONObject(0);
|
|
JSONObject weather = jsonResponse.getJSONArray("weather").getJSONObject(0);
|
|
|
String description = weather.getString("description");
|
|
String description = weather.getString("description");
|
|
|
|
|
|
|
|
- // 4. 输出解析结果
|
|
|
|
|
- System.out.println("=== 天气解析结果 ===");
|
|
|
|
|
- System.out.println("城市: " + cityName);
|
|
|
|
|
- System.out.println("温度: " + String.format("%.2f", tempCelsius) + "°C (原始: " + tempKelvin + "K)");
|
|
|
|
|
- System.out.println("体感温度: " + String.format("%.2f", feelsLikeCelsius) + "°C");
|
|
|
|
|
- System.out.println("湿度: " + humidity + "%");
|
|
|
|
|
- System.out.println("天气状况: " + description);
|
|
|
|
|
- System.out.println("时区偏移: " + (timezoneOffset / 3600) + "小时");
|
|
|
|
|
|
|
+ // 记录日志,不输出到控制台
|
|
|
|
|
+ log.debug("=== 天气解析结果 ===");
|
|
|
|
|
+ log.debug("城市: {}", cityName);
|
|
|
|
|
+ log.debug("温度: {:.2f}°C (原始: {}K)", tempCelsius, tempKelvin);
|
|
|
|
|
+ log.debug("体感温度: {:.2f}°C", feelsLikeCelsius);
|
|
|
|
|
+ log.debug("湿度: {}%", humidity);
|
|
|
|
|
+ log.debug("天气状况: {}", description);
|
|
|
|
|
+ log.debug("时区偏移: {}小时", (timezoneOffset / 3600));
|
|
|
|
|
|
|
|
- // 5. 检查是否包含臭氧数据
|
|
|
|
|
|
|
+ // 检查是否包含臭氧数据
|
|
|
if (jsonResponse.has("air_quality") || jsonResponse.has("o3") || jsonResponse.has("components")) {
|
|
if (jsonResponse.has("air_quality") || jsonResponse.has("o3") || jsonResponse.has("components")) {
|
|
|
- System.out.println("包含空气质量数据");
|
|
|
|
|
|
|
+ log.debug("包含空气质量数据");
|
|
|
} else {
|
|
} else {
|
|
|
- System.out.println("提示: 当前数据不包含臭氧浓度等空气质量指标。");
|
|
|
|
|
|
|
+ log.debug("当前数据不包含臭氧浓度等空气质量指标");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 更新缓存
|
|
|
|
|
+ weatherCache.clear();
|
|
|
|
|
+ weatherCache.put("temperature", tempCelsius);
|
|
|
|
|
+ weatherCache.put("humidity", (double) humidity);
|
|
|
|
|
+ lastUpdateTime = currentTime;
|
|
|
|
|
+ log.debug("天气数据缓存更新成功");
|
|
|
|
|
+
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
- System.err.println("解析JSON时出错: " + e.getMessage());
|
|
|
|
|
- e.printStackTrace();
|
|
|
|
|
|
|
+ log.error("获取天气数据失败:{}", e.getMessage());
|
|
|
|
|
+ // 异常时使用默认值
|
|
|
|
|
+ log.warn("使用默认天气数据,温度:{}°C,湿度:{}%", DEFAULT_TEMPERATURE, DEFAULT_HUMIDITY);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
Map<String, Double> resultMap = new HashMap<>();
|
|
Map<String, Double> resultMap = new HashMap<>();
|
|
|
resultMap.put("temperature", tempCelsius);
|
|
resultMap.put("temperature", tempCelsius);
|
|
|
resultMap.put("humidity", (double) humidity);
|
|
resultMap.put("humidity", (double) humidity);
|