You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaFX天气应用切换首个城市触发400错误求助

问题:JavaFX双城市天气预报应用切换第一个城市报错

报错信息

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1787)
    at javafx.fxml/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1670)
    ...
Caused by: net.aksingh.owmjapis.api.APIException: API call gave error: 400 - Bad Request
    at owm.japis@2.5.3.0/net.aksingh.owmjapis.core.OWM.hourlyWeatherForecastByCityName(OWM.kt:331)
    at WeatherApp/com.dariuszkrygier.model.WeatherForecastFetcher.getWeatherForecast(WeatherForecastFetcher.java:16)
    at WeatherApp/com.dariuszkrygier.controller.MainWindowController.showCurrentWeather(MainWindowController.java:285)
    at WeatherApp/com.dariuszkrygier.controller.MainWindowController.changeFirstCityLocationButtonAction(MainWindowController.java:202)
    ... 58 more

问题代码片段

WeatherForecastFetcher.java

public Weather getWeatherForecast(String cityNameWithCountryCode) throws APIException {
    // 问题行:传入的参数格式无效,触发API 400错误
    HourlyWeatherForecast hourlyWeatherForecast = owm.hourlyWeatherForecastByCityName(cityNameWithCountryCode);
    if (hourlyWeatherForecast.hasRespCode() && hourlyWeatherForecast.getRespCode().equals("200")) {
        return new Weather(hourlyWeatherForecast);
    }
    return null;
}

MainWindowController.java

private void showCurrentWeather(TextField locationField, Label locationName, Label locationDate,
                                ImageView locationImage, Label locationTemp, Label locationWeather
                                ) throws APIException {
    // 问题行:直接传入输入框原始文本,未做清洗校验
    var weather = weatherForecastFetcher.getWeatherForecast(locationField.getText());
    // ... 后续UI渲染逻辑
}

@FXML
void changeFirstCityLocationButtonAction() throws APIException {
    if (firstFieldIsValid()) {
        // 问题行:未捕获API异常,导致JavaFX线程崩溃
        showCurrentWeather(firstCityPicker, firstCity, firstCityFirstDayDate, firstCityFirstDayImage,
                firstCityFirstDayTemp, firstCityFirstDayDescription );
        // ... 其他showNextDays调用
    }
}

排查分析

  1. API 400错误本质:OWM API返回400表示请求参数不符合要求,对比第二个城市正常的情况,说明第一个城市的输入存在格式问题(如含多余空格、空字符串、未遵循"城市名,国家代码"的格式规范)。
  2. 输入校验逻辑薄弱:firstFieldIsValid()的校验规则可能未过滤无效输入,同时获取输入框文本时未做清洗处理。
  3. 异常处理缺失:直接抛出APIException未捕获,导致JavaFX应用线程崩溃。

解决方案

1. 清洗输入参数并添加格式校验

修改getWeatherForecast方法,对输入做清洗和格式校验:

public Weather getWeatherForecast(String cityNameWithCountryCode) throws APIException, IllegalArgumentException {
    // 去除前后空格,避免无效空白字符
    String cleanedInput = cityNameWithCountryCode.trim();
    // 校验输入非空且符合"城市名,国家代码"格式
    if (cleanedInput.isEmpty() || !cleanedInput.contains(",")) {
        throw new IllegalArgumentException("请输入正确格式:城市名,国家代码(例如:London,UK)");
    }
    HourlyWeatherForecast hourlyWeatherForecast = owm.hourlyWeatherForecastByCityName(cleanedInput);
    if (hourlyWeatherForecast.hasRespCode() && hourlyWeatherForecast.getRespCode().equals("200")) {
        return new Weather(hourlyWeatherForecast);
    }
    return null;
}

2. 完善输入框文本获取逻辑

修改showCurrentWeather中获取输入的代码,确保传入清洗后的文本:

var weather = weatherForecastFetcher.getWeatherForecast(locationField.getText().trim());

3. 强化输入校验规则

更新firstFieldIsValid(),确保过滤无效输入:

private boolean firstFieldIsValid() {
    String input = firstCityPicker.getText().trim();
    // 校验非空且包含逗号分隔符
    return !input.isEmpty() && input.contains(",");
}

4. 添加异常捕获避免程序崩溃

修改changeFirstCityLocationButtonAction方法,捕获异常并给用户友好提示:

@FXML
void changeFirstCityLocationButtonAction() {
    if (firstFieldIsValid()) {
        try {
            showCurrentWeather(firstCityPicker, firstCity, firstCityFirstDayDate, firstCityFirstDayImage,
                    firstCityFirstDayTemp, firstCityFirstDayDescription );
            // day2
            showNextDays(firstCityPicker, 8, firstCitySecondDayDate, firstCitySecondDayImage,
                    firstCitySecondDayTemp, firstCitySecondDayDescription);
            // day3
            showNextDays(firstCityPicker, 16, firstCityThirdDayDate, firstCityThirdDayImage,
                    firstCityThirdDayTemp, firstCityThirdDayDescription);
            // day4
            showNextDays(firstCityPicker, 24, firstCityFourthDayDate, firstCityFourthDayImage,
                    firstCityFourthDayTemp, firstCityFourthDayDescription);
            // day5
            showNextDays(firstCityPicker, 32, firstCityFifthDayDate, firstCityFifthDayImage,
                    firstCityFifthDayTemp, firstCityFifthDayDescription);
        } catch (APIException e) {
            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setTitle("获取天气失败");
            alert.setHeaderText("API请求错误");
            alert.setContentText("无法获取天气数据,请检查城市名称是否正确");
            alert.showAndWait();
        } catch (IllegalArgumentException e) {
            Alert alert = new Alert(Alert.AlertType.WARNING);
            alert.setTitle("输入格式错误");
            alert.setHeaderText("请检查输入内容");
            alert.setContentText(e.getMessage());
            alert.showAndWait();
        } catch (Exception e) {
            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setTitle("程序错误");
            alert.setHeaderText("未知错误");
            alert.setContentText("操作失败,请重试");
            alert.showAndWait();
        }
    }
}

内容的提问来源于stack exchange,提问作者dar1o

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 18:57:04