在許多 Java 應用中,需要集成實時天氣數據——無論是智能家居聯動、出行提醒還是農業監測。中國天氣網(weather.com.cn)作為官方氣象數據源,提供免費的移動端 API,返回結構化 JSON,適合服務端直接調用。本文以哈爾濱(編碼 101050101)為例,完整演示從 HTTP 請求到數據解析、業務邏輯封裝的全流程代碼。
DefaultHttpClient、HttpGet、BasicResponseHandler)JsonParser、JsonObject、JsonElement)<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
public class WeatherService {
private static final String API_URL_TEMPLATE = "https://m.weather.com.cn/data/%s.html";
private static final String CITY_CODE_HARBIN = "101050101";
public String getWeatherInfo() {
StringBuilder info = new StringBuilder();
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
String url = String.format(API_URL_TEMPLATE, CITY_CODE_HARBIN);
HttpGet httpGet = new HttpGet(url);
String responseBody = httpClient.execute(httpGet, new BasicResponseHandler());
// 解析 JSON
JsonObject weatherInfo = JsonParser.parseString(responseBody)
.getAsJsonObject()
.get("weatherinfo")
.getAsJsonObject();
String updTime = weatherInfo.get("fchh").getAsString();
if (updTime == null || updTime.trim().isEmpty()) {
return "天氣數據更新時間為空";
}
// 根據發布時間(18點為分界)選擇不同字段組合
if (!"18".equals(updTime.trim())) {
appendStandardForecast(weatherInfo, info);
} else {
appendEveningForecast(weatherInfo, info);
}
} catch (Exception e) {
// 生產環境建議記錄日誌並拋出自定義異常
return "獲取天氣失敗:" + e.getMessage();
}
return info.toString();
}
/** 非 18 點發布:直接使用 today/tomorrow 字段 */
private void appendStandardForecast(JsonObject jo, StringBuilder sb) {
sb.append("明天:")
.append(jo.get("temp1").getAsString()).append(" ")
.append(jo.get("weather1").getAsString()).append(" ")
.append(jo.get("wind1").getAsString()).append("\n");
sb.append("今天:")
.append(jo.get("temp2").getAsString()).append(" ")
.append(jo.get("weather2").getAsString()).append(" ")
.append(jo.get("wind2").getAsString()).append("\n");
}
/** 18 點發布:需拆分/組合 temp1~temp3、weather1~weather3 */
private void appendEveningForecast(JsonObject jo, StringBuilder sb) {
// 溫度範圍拆分邏輯
String[] t1 = jo.get("temp1").getAsString().split("~");
String[] t2 = jo.get("temp2").getAsString().split("~");
String[] t3 = jo.get("temp3").getAsString().split("~");
String tomorrowTemp = t1[1] + "~" + t2[0];
String todayTemp = t2[1] + "~" + t3[0];
// 天氣現象合併邏輯(處理「轉」)
String tomorrowWeather = mergeWeather(jo.get("weather1").getAsString(), jo.get("weather2").getAsString());
String todayWeather = mergeWeather(jo.get("weather2").getAsString(), jo.get("weather3").getAsString());
sb.append("明天:").append(tomorrowTemp).append(" ").append(tomorrowWeather).append(" ")
.append(jo.get("wind2").getAsString()).append("\n");
sb.append("今天:").append(todayTemp).append(" ").append(todayWeather).append(" ")
.append(jo.get("wind3").getAsString()).append("\n");
}
private String mergeWeather(String w1, String w2) {
String part1 = w1.contains("轉") ? w1.split("轉")[1] : w1;
String part2 = w2.contains("轉") ? w2.split("轉")[0] : w2;
return part1.equalsIgnoreCase(part2) ? part1 : part1 + "轉" + part2;
}
}
中國天氣網 API 在 18:00 發布的預報 包含三個時段(temp1/2/3、weather1/2/3),非 18:00 僅含兩個時段。代碼通過 fchh 字段判斷發布小時,動態選擇解析策略,保證全天候數據正確。
如「晴轉多雲」與「多雲轉陰」,需提取中間狀態組合為「多雲轉多雲」→簡化為「多雲」;若不一致則保留「晴轉陰」。mergeWeather() 方法封裝了此邏輯,提高代碼復用性。
try-with-resources 確保 HttpClient 正確關閉,避免連接洩漏RequestConfig.custom().setConnectTimeout(3000).setSocketTimeout(5000).build()Map<String, String> cityCodeMap,支援城市名/拼音/ID 多維查詢https://,提升傳輸安全性本文提供了一個開箱即用、結構清晰、兼容 API 多種返回格式的 Java 天氣服務實現。通過合理的模組化設計(策略模式處理不同時段、工具方法複用邏輯),代碼具備良好的可維護性與擴展性,可直接集成至 Spring Boot、微服務或定時任務項目中。