openweathermap是最适合初学者的免费天气api:无需实名认证、免费额度充足、文档清晰、json结构规整;java 11+推荐用httpclient发送get请求并用org.json解析,注意错误处理与打包依赖问题。

怎么选免费又靠谱的天气API
免费天气接口现在基本都要求注册,但不是所有平台都适合初学者。OpenWeatherMap 是目前最友好的选择:不需要实名认证、free tier 每分钟 1000 次调用足够练手、文档清晰、返回 JSON 结构规整。别碰那些要“企业资质”或“备案号”的接口,也别信“永久免费不限量”的小网站——大概率第二天就 401 或返回乱码。
- 注册后在
<a href="https://www.php.cn/link/055bac208ceea65244da625816501e94">https://www.php.cn/link/055bac208ceea65244da625816501e94</a>页面拿到你的APPID,这是每次请求必须带的参数 - 接口地址示例:
<a href="https://www.php.cn/link/6903a6decc9cc3ddea7cd1a0d9091878">https://www.php.cn/link/6903a6decc9cc3ddea7cd1a0d9091878</a> -
units=metric返回摄氏度,units=imperial是华氏度;不加这个参数默认是开尔文,初学者容易看懵
Java里怎么发HTTP请求拿JSON数据
Java 11+ 自带 HttpClient,不用额外引 OkHttp 或 Apache HttpClient,省去依赖冲突麻烦。但注意:别用 URL.openConnection(),它默认不支持 HTTPS 重定向,OpenWeatherMap 的地址会 301 跳转,不处理就卡住或报 java.io.IOException: Server returned HTTP response code: 403。
- 用
HttpClient.newBuilder().build()创建客户端,别用静态单例(测试时容易 mock 不掉) - 请求必须设
GET方法,并在 URL 里拼全参数(不要试图用HttpRequest.BodyPublishers.ofString()发 POST) - 响应体用
HttpResponse.BodyHandlers.ofString()拿字符串,别直接转InputStream——编码问题会导致中文城市名变???
HttpClient client = HttpClient.newBuilder().build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.openweathermap.org/data/2.5/weather?q=Shanghai&appid=abc123&units=metric"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body()); // 看一眼原始 JSON,确认没出错
解析JSON时最容易崩在哪几个地方
Java 没有内置 JSON 解析器,得靠第三方库。推荐用 org.json(轻量、无依赖、单 jar),别一上来就上 jackson-databind——光是 @JsonCreator 和 ObjectMapper 配置就能卡半天。
常见崩点:
立即学习“Java免费学习笔记(深入)”;
- OpenWeatherMap 返回的
weather是数组,哪怕只有一条数据也是[{"main":"Clouds","description":"overcast clouds"}],直接obj.getString("weather")必抛JSONException -
main.temp是数字,但某些城市(比如极地站点)可能为null,不做判空就NullPointerException - 城市名输错或网络超时,返回的是错误 JSON:
{"cod":"404","message":"city not found"},别假设永远有main字段
JSONObject root = new JSONObject(response.body());
if ("404".equals(root.optString("cod"))) {
System.out.println("查不到这个城市:" + root.optString("message"));
return;
}
JSONObject main = root.getJSONObject("main");
double temp = main.optDouble("temp", -999); // optDouble 自动兜底
JSONArray weatherArr = root.getJSONArray("weather");
String desc = weatherArr.getJSONObject(0).optString("description", "unknown");
为什么本地跑通了,打包成jar就报错
最常见的原因是:JAR 包里没把 org.json 的 class 打进去,或者用了 Maven Shade 插件但没配置 Minijar 合并策略,导致运行时找不到 org.json.JSONObject。
- 检查
java -jar your-app.jar报的错是不是NoClassDefFoundError: org/json/JSONObject - 如果用 Maven,确保
pom.xml里org.json的 scope 是compile(不是provided) - 打包时用
maven-assembly-plugin或spring-boot-maven-plugin(哪怕不用 Spring Boot),别用默认mvn package——它只打源码,不打依赖
真正的坑在于:有些 IDE(比如老版本 IntelliJ)右键 “Run” 时自动加了 classpath,掩盖了依赖缺失问题,一到命令行就露馅。所以写完立刻试 java -cp "target/your-app.jar:lib/*" com.example.Main,别等部署才发现。










