本文示範如何使用 Java 串接聚合數據 的「全國天氣預報 API」,包含取得城市列表、依城市名稱/ID 查詢天氣、取得天氣類型代碼對照表等核心功能。適用於需要整合即時氣象資料的應用開發。
該 API 提供六個子接口,本範例主要使用:
開發策略:先呼叫城市列表接口建立城市名稱與 ID 對照,再依需求查詢特定城市天氣。
封裝 HTTP GET/POST 請求,支援參數傳遞與回應處理:
package juheAPI;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
public class PureNetUtil {
/** GET 請求封裝 */
public static String get(String url) {
return post(url, null);
}
/** POST 請求核心實作 */
public static String post(String url, Map param) {
HttpURLConnection conn = null;
try {
URL u = new URL(url);
conn = (HttpURLConnection) u.openConnection();
if (param != null) {
conn.setDoOutput(true);
conn.setRequestMethod("POST");
try (OutputStream out = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out))) {
StringBuilder sb = new StringBuilder();
for (Map.Entry entry : param.entrySet()) {
sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
// 移除尾端 '&'
writer.write(sb.deleteCharAt(sb.length() - 1).toString());
}
}
conn.connect();
if (conn.getResponseCode() == 200) {
try (InputStream in = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line).append(System.lineSeparator());
}
// 移除最後換行符
String result = sb.toString();
return result.substring(0, result.length() - System.lineSeparator().length());
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (conn != null) conn.disconnect();
}
return null;
}
}
package juheAPI;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
public class GetCityList {
private static final String API_URL = "https://v.juhe.cn/weather/citys?key=YOUR_API_KEY";
/** 取得完整城市列表原始 JSON */
public static String execute() {
return PureNetUtil.get(API_URL);
}
/** 根據城市名稱 (支援模糊比對) 取得城市 ID */
public static String getIDByCityName(String cityName) {
String result = execute();
if (result == null) return null;
JSONObject obj = JSONObject.fromObject(result);
String resultCode = obj.getString("resultcode");
if ("200".equals(resultCode)) {
String cityListJson = obj.getString("result");
JSONArray arr = JSONArray.fromObject(cityListJson);
for (Object o : arr) {
JSONObject cityObj = JSONObject.fromObject(o.toString());
// 結構範例:{"id":"2","province":"北京","city":"北京","district":"海淀"}
String district = cityObj.getString("district");
// 支援完整名稱或包含關係 (如「蘇州」匹配「蘇州市」)
if (district.equals(cityName) || district.contains(cityName)) {
return cityObj.getString("id");
}
}
}
return null;
}
public static void main(String[] args) {
System.out.println(getIDByCityName("香港"));
}
}
package juheAPI;
import net.sf.json.JSONObject;
public class WeatherReportByCity {
/** 根據城市名稱查詢天氣 (回傳完整 JSON) */
public static String execute(String cityName) {
String url = "https://v.juhe.cn/weather/index?cityname=" + cityName
+ "&key=YOUR_API_KEY&format=2"; // format=2 回傳 JSON
return PureNetUtil.get(url);
}
/** 解析並取得今日溫度範圍 (如 "8℃~20℃") */
public static String getTodayTemperatureByCity(String city) {
String result = execute(city);
if (result == null) return null;
JSONObject obj = JSONObject.fromObject(result);
if ("200".equals(obj.getString("resultcode"))) {
JSONObject resultObj = JSONObject.fromObject(obj.getString("result"));
JSONObject todayObj = JSONObject.fromObject(resultObj.getString("today"));
return todayObj.getString("temperature");
}
return null;
}
public static void main(String[] args) {
System.out.println(getTodayTemperatureByCity("蘇州"));
}
}
package juheAPI;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
public class GetWeatherSignAndTypeList {
private static final String URL = "https://v.juhe.cn/weather/uni?key=YOUR_API_KEY";
public static String execute() {
return PureNetUtil.get(URL);
}
/** 根據 weather ID (wid) 取得天氣名稱 */
public static String getWeatherByWid(String wid) {
String result = execute();
if (result == null) return null;
JSONObject obj = JSONObject.fromObject(result);
if ("200".equals(obj.getString("resultcode"))) {
JSONArray arr = JSONArray.fromObject(obj.getString("result"));
for (Object o : arr) {
JSONObject item = JSONObject.fromObject(o.toString());
if (item.getString("wid").equals(wid)) {
return item.getString("weather");
}
}
}
return null;
}
public static void main(String[] args) {
System.out.println(getWeatherByWid("10")); // 例:查詢 wid=10 的天氣名稱
}
}
| 狀態碼 | 說明 | 處理建議 |
|---|---|---|
| 200 | 請求成功 | 正常解析 result 欄位 |
| 201 | 無查詢結果 | 檢查城市名稱拼音/拼寫 |
| 202 | 查詢參數錯誤 | 確認 cityname/cityid 格式 |
| 203 | Key 錯誤或餘額不足 | 檢查 API Key 是否正確、額度是否用盡 |
| 204 | 請求頻率超限 | 降低呼叫頻率或升級方案 |
專案使用 net.sf.json-lib 處理 JSON 解析,Maven 依賴如下:
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
本範例完整展示了從 API 申請、網路層封裝、JSON 解析到業務邏輯實作的完整流程。採用模組化設計,各功能獨立封裝,便於維護與擴充。實際部署時請務必妥善保管 API Key,並依據業務需求實作適當的快取與容錯機制。