首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 調用中國天氣網 API 獲取實時天氣預報完整指南

     編輯:Java 相關知識

項目背景與需求

在許多 Java 應用中,需要集成實時天氣數據——無論是智能家居聯動、出行提醒還是農業監測。中國天氣網(weather.com.cn)作為官方氣象數據源,提供免費的移動端 API,返回結構化 JSON,適合服務端直接調用。本文以哈爾濱(編碼 101050101)為例,完整演示從 HTTP 請求到數據解析、業務邏輯封裝的全流程代碼。

核心依賴

  • Apache HttpClient 4.x(DefaultHttpClient、HttpGet、BasicResponseHandler)
  • Google Gson(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;
    }
}

關鍵技術點解析

1. API 回傳結構差異處理

中國天氣網 API 在 18:00 發布的預報 包含三個時段(temp1/2/3、weather1/2/3),非 18:00 僅含兩個時段。代碼通過 fchh 字段判斷發布小時,動態選擇解析策略,保證全天候數據正確。

2. 天氣現象「轉」的智能合併

如「晴轉多雲」與「多雲轉陰」,需提取中間狀態組合為「多雲轉多雲」→簡化為「多雲」;若不一致則保留「晴轉陰」。mergeWeather() 方法封裝了此邏輯,提高代碼復用性。

3. 資源管理與異常處理

  • 使用 try-with-resources 確保 HttpClient 正確關閉,避免連接洩漏
  • 統一捕獲異常並返回友好提示,生產環境建議接入日誌框架(SLF4J + Logback)記錄堆棧
  • 可額外增加連接/讀取超時配置:RequestConfig.custom().setConnectTimeout(3000).setSocketTimeout(5000).build()

擴展建議

  1. 城市編碼映射表:維護 Map<String, String> cityCodeMap,支援城市名/拼音/ID 多維查詢
  2. 緩存策略:天氣數據時效性較高,引入 Caffeine/Redis 緩存 30-60 分鐘,減少外部調用壓力
  3. 熔斷降級:接入 Resilience4j 或 Sentinel,API 失敗時返回緩存舊數據或默認提示
  4. HTTPS 遷移:官方已支援 HTTPS,建議將模板 URL 升級為 https://,提升傳輸安全性

總結

本文提供了一個開箱即用、結構清晰、兼容 API 多種返回格式的 Java 天氣服務實現。通過合理的模組化設計(策略模式處理不同時段、工具方法複用邏輯),代碼具備良好的可維護性與擴展性,可直接集成至 Spring Boot、微服務或定時任務項目中。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved