SpringBoot整合高德地图完成天气预报功能实战

6 阅读5分钟

引言

最近天气变化无常,很多应用都需要集成天气预报功能。作为后端开发者,我们经常需要为移动端、Web端提供天气数据接口。今天就来聊聊如何用SpringBoot整合高德地图API,快速实现一个实用的天气预报服务。

高德地图作为国内领先的地图服务商,提供了丰富的天气API接口,数据准确、更新及时,而且免费额度相当 generous。我们通过SpringBoot来封装这些能力,让天气服务变得更加稳定可靠。

整体架构设计

我们的天气服务架构是这样的:

┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
│   前端应用层     │───▶│   SpringBoot服务层 │───▶│   高德天气API    │
│                 │    │                  │    │                 │
│  移动端/PC端    │    │  Controller      │    │  实时天气数据    │
│  天气查询界面    │    │  Service         │    │  预报天气数据    │
└─────────────────┘    └──────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │    缓存层        │
                       │                 │
                       │  Redis缓存      │
                       │  本地缓存       │
                       └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │    配置管理      │
                       │                 │
                       │  API Key管理    │
                       │  城市编码映射    │
                       └─────────────────┘

核心设计要点

1. API调用策略

高德天气API的特点:

  • 实况天气每小时更新多次
  • 预报天气每天更新3次(8点、11点、18点)
  • 有调用频次限制
  • 返回JSON格式数据

所以我们需要合理的缓存策略:

  • 实况天气缓存30分钟
  • 预报天气缓存2小时
  • 失败重试机制
  • 降级处理

2. 数据模型设计

天气数据结构化处理:

// 实况天气实体
@Data
public class LiveWeather {
    private String province;      // 省份
    private String city;          // 城市
    private String adcode;        // 城市编码
    private String weather;       // 天气现象
    private String temperature;   // 温度
    private String windDirection; // 风向
    private String windPower;     // 风力
    private String humidity;      // 湿度
    private String reportTime;    // 发布时间
}

// 预报天气实体
@Data
public class ForecastWeather {
    private String city;
    private String adcode;
    private String province;
    private String reportTime;
    private List<WeatherCast> casts; // 预报列表
}

@Data
public class WeatherCast {
    private String date;          // 日期
    private String week;          // 星期
    private String dayWeather;    // 白天天气
    private String nightWeather;  // 夜间天气
    private String dayTemp;       // 白天温度
    private String nightTemp;     // 夜间温度
    private String dayWind;       // 白天风向
    private String nightWind;     // 夜间风向
    private String dayPower;      // 白天风力
    private String nightPower;    // 夜间风力
}

3. 服务层设计

核心服务类设计:

@Service
public class WeatherService {
    
    // 获取实况天气
    public LiveWeather getLiveWeather(String cityCode) {
        // 1. 先查缓存
        // 2. 缓存未命中则调用API
        // 3. 更新缓存
        // 4. 返回结果
    }
    
    // 获取预报天气
    public ForecastWeather getForecastWeather(String cityCode) {
        // 类似处理逻辑
    }
    
    // 城市名称转编码
    public String getCityCode(String cityName) {
        // 城市名称映射到adcode
    }
}

4. 缓存策略实现

@Component
public class WeatherCacheManager {
    
    // 实况天气缓存30分钟
    @Cacheable(value = "live_weather", key = "#cityCode")
    public LiveWeather getLiveWeatherFromCache(String cityCode) {
        return weatherService.getLiveWeatherFromApi(cityCode);
    }
    
    // 预报天气缓存2小时
    @Cacheable(value = "forecast_weather", key = "#cityCode")
    public ForecastWeather getForecastWeatherFromCache(String cityCode) {
        return weatherService.getForecastWeatherFromApi(cityCode);
    }
}

关键实现细节

1. 高德API调用封装

@Component
public class GaodeWeatherClient {
    
    private final RestTemplate restTemplate;
    private final String apiKey;
    private final String baseUrl = "https://restapi.amap.com/v3/weather/weatherInfo";
    
    public GaodeWeatherResponse getWeather(String cityCode, String extensions) {
        String url = String.format("%s?city=%s&key=%s&extensions=%s", 
                                 baseUrl, cityCode, apiKey, extensions);
        
        try {
            ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
            return parseResponse(response.getBody());
        } catch (Exception e) {
            // 异常处理和降级
            return getFallbackWeather(cityCode);
        }
    }
}

2. 城市编码管理

@Component
public class CityCodeManager {
    
    private Map<String, String> cityCodeMap = new HashMap<>();
    
    @PostConstruct
    public void initCityCodes() {
        // 初始化常用城市编码
        cityCodeMap.put("北京", "110000");
        cityCodeMap.put("上海", "310000");
        cityCodeMap.put("广州", "440100");
        cityCodeMap.put("深圳", "440300");
        // ... 更多城市
    }
    
    public String getCityCode(String cityName) {
        return cityCodeMap.getOrDefault(cityName, "110000"); // 默认北京
    }
}

3. 控制器设计

@RestController
@RequestMapping("/api/weather")
public class WeatherController {
    
    @Autowired
    private WeatherService weatherService;
    
    // 获取实况天气
    @GetMapping("/live/{city}")
    public ResponseEntity<LiveWeather> getLiveWeather(@PathVariable String city) {
        try {
            LiveWeather weather = weatherService.getLiveWeather(city);
            return ResponseEntity.ok(weather);
        } catch (Exception e) {
            return ResponseEntity.status(500).build();
        }
    }
    
    // 获取预报天气
    @GetMapping("/forecast/{city}")
    public ResponseEntity<ForecastWeather> getForecastWeather(@PathVariable String city) {
        try {
            ForecastWeather weather = weatherService.getForecastWeather(city);
            return ResponseEntity.ok(weather);
        } catch (Exception e) {
            return ResponseEntity.status(500).build();
        }
    }
}

业务场景应用

场景一:移动端天气展示

APP首页需要展示用户所在城市的天气:

  1. 通过IP定位获取城市
  2. 调用天气接口获取实况数据
  3. 展示温度、天气状况、风力等信息

场景二:出行提醒服务

根据天气预报提供出行建议:

  1. 获取未来3天天气预报
  2. 分析天气变化趋势
  3. 给出出行提醒(如带伞、添衣等)

场景三:商户经营分析

帮助商户根据天气调整经营策略:

  1. 餐饮业根据天气推荐菜品
  2. 服装业根据温度变化调整库存
  3. 户外活动根据天气安排时间

最佳实践建议

1. 性能优化

  • 合理设置缓存时间
  • 批量查询多个城市天气
  • 异步更新缓存数据

2. 容错处理

  • API调用失败时的降级策略
  • 网络异常时的重试机制
  • 数据异常时的默认值处理

3. 安全考虑

  • API Key的安全存储
  • 请求频率限制
  • 敏感信息脱敏

4. 监控告警

  • API调用成功率监控
  • 响应时间监控
  • 缓存命中率监控

写在最后

天气预报看似简单,但要做好一个稳定可靠的天气服务并不容易。关键是要理解业务需求,在准确性和实时性之间找到平衡点。

记住几个要点:

  1. 合理使用缓存,避免频繁调用API
  2. 做好异常处理,保证服务稳定性
  3. 监控API使用情况,及时发现问题
  4. 根据业务场景优化数据结构

通过SpringBoot整合高德地图天气API,我们可以快速搭建一个专业级的天气服务,为各种应用场景提供支撑。


服务端技术精选
作者:技术博主
博客:www.jiangyi.space