导读:本期聚焦于赵六创作的《Spring Boot 整合天气 API 如何实现城市天气查询与天气预警推送?》,敬请观看详情。天气数据是很多业务系统都会用到的外部资源,比如出行平台、物流调度、智慧农业等场景都离不开实时的天气信息。本文介绍如何在 Spring Boot 项目中整合第三方天气 API,通过 RestTemplate 完成城市天气查询接口的封装,返回温度、湿度、风力等结构化数据,并在此基础上实现天气预警信息的定时拉取与推送。文章涵盖 API 选型、接口调用、JSON 解析、异常重试以及定时任务设计等核心环节,附带完整可运行的代码示例,帮助开发者快速搭建一套稳定可用的天气服务模块。

在出行类应用、物流调度平台或者智慧园区系统中,实时天气数据几乎是刚需。将第三方天气 API 整合进 Spring Boot 项目并不复杂,但要做得稳定、可维护,就需要在接口封装、异常处理、数据缓存和预警推送等环节下一番功夫。本文将以一套完整的方案为主线,从 API 选型到代码实现,逐步搭建一个支持城市天气查询与天气预警功能的服务模块。

Spring Boot 整合天气 API 如何实现城市天气查询与天气预警推送?

一、天气 API 选型与项目准备

市面上常见的天气 API 有和风天气、心知天气、OpenWeatherMap 等。国内项目建议优先考虑和风天气或心知天气,它们对国内城市覆盖更全,中文支持也更好。本文以和风天气为例,其免费版即支持城市天气查询和实时预警接口,足够开发调试使用。

使用前需要先注册账号并创建一个项目应用,获得 API Key。接下来创建一个 Spring Boot 项目,引入必要的依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</groupId>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

application.yml 中配置 API 的基础地址和密钥。将密钥放在配置文件而不是硬编码在代码里,方便后续切换环境:

weather:
  api:
    base-url: https://devapi.qweather.com
    key: 你的API密钥
    timeout: 3000

同时通过 @ConfigurationProperties 定义一个配置类,把配置项映射成 Java 对象,这样在业务代码中注入使用更加干净整洁。

二、封装天气查询接口

调用第三方 API 的方式有很多,可以用 RestTemplateWebClient 或者 OkHttp。对于传统的同步调用场景,RestTemplate 足够简单实用。先定义一个配置类注册 RestTemplate Bean,并设置超时时间:

@Configuration
public class HttpConfig {

    @Value("${weather.api.timeout}")
    private int timeout;

    @Bean
    public RestTemplate restTemplate() {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(timeout);
        factory.setReadTimeout(timeout);
        return new RestTemplate(factory);
    }
}

接下来定义天气数据的实体类。和风天气返回的 JSON 结构是嵌套的 now、daily 等节点,建议按需定义 DTO,只保留业务关心的字段:

@Data
public class WeatherResult {
    private String code;
    private String updateTime;
    private NowInfo now;
    private List<DailyInfo> daily;

    @Data
    public static class NowInfo {
        private String temp;      // 当前温度
        private String humidity;  // 湿度
        private String windDir;   // 风向
        private String windScale; // 风力等级
        private String text;      // 天气现象
    }

    @Data
    public static class DailyInfo {
        private String fxDate;
        private String tempMax;
        private String tempMin;
        private String textDay;
    }
}

核心的 Service 层负责拼接请求参数、发起调用并反序列化结果。注意城市 ID 需要先通过城市查询接口获取,也可以在数据库中维护一张城市映射表,避免每次请求都额外调用一次查询接口:

@Service
@RequiredArgsConstructor
public class WeatherService {

    private final RestTemplate restTemplate;

    @Value("${weather.api.base-url}")
    private String baseUrl;

    @Value("${weather.api.key}")
    private String apiKey;

    public WeatherResult getWeather(String locationId) {
        String url = baseUrl + "/v7/weather/now?location={location}&key={key}";
        try {
            return restTemplate.getForObject(url, WeatherResult.class, locationId, apiKey);
        } catch (RestClientException e) {
            // 记录日志并抛出业务异常
            log.error("查询天气失败, location={}", locationId, e);
            throw new BizException("天气服务暂时不可用,请稍后重试");
        }
    }
}

最后暴露一个 Controller 接口给前端调用,接收城市名称或 ID,返回统一格式的响应体。前端拿到结构化数据后即可渲染温度、湿度、未来几天的预报等信息。

三、天气预警的定时拉取与推送

天气预警的时效性要求高,不适合让用户每次主动查询。更好的做法是服务端定时拉取预警接口,一旦发现目标城市出现新的预警信息,就通过消息推送、邮件或短信等方式通知相关人员。

Spring Boot 提供了 @Scheduled 注解可以快速实现定时任务。设置每五分钟拉取一次预警数据,将预警 ID 与已发送记录对比,避免重复推送:

@Component
@RequiredArgsConstructor
public class WarningTask {

    private final WeatherService weatherService;
    private final PushService pushService;
    private final Set<String> sentIds = ConcurrentHashMap.newKeySet();

    @Scheduled(fixedRate = 5 * 60 * 1000)
    public void fetchWarning() {
        List<City> cities = cityMapper.selectWatchedCities();
        for (City city : cities) {
            WarningResult result = weatherService.getWarning(city.getId());
            if (result == null || result.getWarning() == null) {
                continue;
            }
            for (WarningItem item : result.getWarning()) {
                if (sentIds.add(item.getAlertId())) {
                    pushService.push(city.getName(), item.getTitle(), item.getText());
                }
            }
        }
    }
}

使用内存 Set 去重只适合单实例部署。如果服务是多节点部署,建议把已发送的预警 ID 存入 Redis 或数据库,利用分布式锁保证同一预警只推送一次。定时任务的启动类上别忘了加 @EnableScheduling 注解。

四、稳定性优化:缓存、重试与降级

第三方 API 普遍有调用频率限制,滥用不仅浪费配额,还可能被限流。天气数据本身更新频率不高,实时接口每十分钟变化一次就足够了,因此引入本地缓存非常必要。可以直接使用 Caffeine:

@Cacheable(value = "weather", key = "#locationId", unless = "#result == null")
public WeatherResult getWeather(String locationId) {
    // 实际调用逻辑
}

缓存过期时间设置为十分钟,相同城市的重复请求直接命中缓存,第三方调用次数能下降百分之九十以上。对于偶发的网络抖动,可以加上简单的重试机制,例如使用 Spring Retry 的 @Retryable 注解,最多重试两次,间隔一秒。

降级策略同样重要。当第三方 API 长时间不可用时,可以返回上一次成功的缓存数据并标记数据更新时间,或者切换到备用 API 源。这种多级兜底能保证业务不因外部依赖故障而完全瘫痪。此外建议对返回的 code 字段做校验,第三方接口即使 HTTP 状态码为 200,业务上也可能返回错误码,只有显式判断才能准确区分成功与失败。

总结一下,整合天气 API 的关键在于四点:配置与密钥管理、接口封装与 DTO 映射、定时任务做预警推送、缓存与重试保障稳定性。按照本文的方案落地,一个可靠的城市天气服务模块就可以快速投入业务使用了。

Spring Boot天气APIRestTemplate修改时间:2026-09-02 16:32:58

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260902/49043.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。