在出行类应用、物流调度平台或者智慧园区系统中,实时天气数据几乎是刚需。将第三方天气 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 的方式有很多,可以用 RestTemplate、WebClient 或者 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