SpringBoot整合高德地图完成天气预报功能
一、前言
在当今数字化时代,天气预报功能在众多应用中扮演着重要角色。通过整合高德地图提供的天气API,我们可以轻松地在自己的SpringBoot项目中实现这一功能,为用户提供实时和未来几天的天气信息。本文将详细介绍如何在SpringBoot项目中整合高德地图的天气预报功能,包括环境搭建、代码实现、定时任务设置等关键步骤,确保大家能够按照教程成功实现功能。
二、环境搭建
(一)创建SpringBoot项目
-
使用Spring Initializr
- 访问 Spring Initializr 网站。
- 选择项目元数据,如项目名称、包名等。
- 添加依赖:
Spring Web
、Spring Boot DevTools
(可选,方便开发时热部署)。 - 点击"Generate"按钮下载项目压缩包,解压后导入到你的IDE(如IntelliJ IDEA或Eclipse)中。
-
项目结构示例
arduinospring-boot-weather ├── src │ ├── main │ │ ├── java │ │ │ └── com.example.weather │ │ │ ├── controller │ │ │ ├── service │ │ │ ├── entity │ │ │ ├── config │ │ │ └── WeatherApplication.java │ │ └── resources │ │ ├── application.yml │ │ └── static │ └── test │ └── java │ └── com.example.weather │ └── WeatherApplicationTests.java └── pom.xml
(二)添加依赖
在pom.xml
文件中添加必要的依赖,确保项目能够使用Spring Web和定时任务等功能。
xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
(三)高德地图API申请
-
注册高德开放平台账号
- 访问 高德开放平台 官网,注册账号并登录。
- 在"控制台"中创建应用,获取
API Key
。该Key
将用于后续调用高德地图的天气API。
-
配置
application.yml
- 将获取到的
API Key
和天气API的URL配置到application.yml
文件中。
yamlamap-weather-config: weatherurl: https://restapi.amap.com/v3/weather/weatherInfo key: YOUR_API_KEY
- 将获取到的
三、代码实现
(一)配置类
创建一个配置类AmapWeatherConfig
,用于读取application.yml
中的高德地图天气API配置。
java
package com.example.weather.config;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "amap-weather-config")
@Getter
@Setter
public class AmapWeatherConfig {
private String weatherurl;
private String key;
}
(二)实体类
定义两个实体类Live
和WeatherForecast
,分别用于存储实时天气和预报天气的数据。
实时天气实体类Live
java
package com.example.weather.entity;
import lombok.Data;
@Data
public class Live {
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;
}
预报天气实体类WeatherForecast
java
package com.example.weather.entity;
import lombok.Data;
@Data
public class WeatherForecast {
private String province;
private String city;
private String adcode;
private String date;
private String week;
private String dayWeather;
private String dayWeatherImg;
private String nightWeather;
private String nightWeatherImg;
private String dayTemp;
private String nightTemp;
private String dayWind;
private String nightWind;
private String dayPower;
private String nightPower;
private String reportTime;
}
(三)服务层
创建WeatherService
类,用于调用高德地图的天气API,并将返回的数据封装到实体类中。
java
package com.example.weather.service;
import com.example.weather.config.AmapWeatherConfig;
import com.example.weather.entity.Live;
import com.example.weather.entity.WeatherForecast;
import com.example.weather.common.WeatherConstant;
import com.example.weather.enums.WeatherType;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Service
@Slf4j
public class WeatherService {
@Autowired
private RestTemplate restTemplate;
@Autowired
private AmapWeatherConfig amapWeatherConfig;
/**
* 获取实时天气
*
* @param adcode 城市编码
* @return 实时天气实体类
*/
public Live getLiveWeather(String adcode) {
String sendUrl = amapWeatherConfig.getWeatherurl() +
"?key=" + amapWeatherConfig.getKey() +
"&city=" + adcode +
"&extensions=base";
ResponseEntity<GaoDeResult> responseEntity = restTemplate.getForEntity(sendUrl, GaoDeResult.class);
// 请求异常,可能由于网络等原因
HttpStatus statusCode = responseEntity.getStatusCode();
if (!HttpStatus.OK.equals(statusCode)) {
log.info("Request for Gaode interface error");
return null;
}
// 请求失败
GaoDeResult gaoDeResult = responseEntity.getBody();
String status = gaoDeResult.getStatus();
if (!status.equals(WeatherConstant.SUCCESS)) {
log.info("Request for Gaode interface failed");
return null;
}
List<Live> lives = gaoDeResult.getLives();
if (CollectionUtils.isEmpty(lives)) {
return null;
}
// 实况天气
return lives.get(0);
}
/**
* 获取未来几天的天气预报
*
* @param adcode 城市编码
* @return 天气预报列表
*/
public List<WeatherForecast> getForecastWeather(String adcode) {
String sendUrl = amapWeatherConfig.getWeatherurl() +
"?key=" + amapWeatherConfig.getKey() +
"&city=" + adcode +
"&extensions=all";
ResponseEntity<GaoDeResult> responseEntity = restTemplate.getForEntity(sendUrl, GaoDeResult.class);
// 请求异常,可能由于网络等原因
HttpStatus statusCode = responseEntity.getStatusCode();
if (!HttpStatus.OK.equals(statusCode)) {
log.info("Request for Gaode interface error");
return Collections.emptyList();
}
// 请求失败
GaoDeResult gaoDeResult = responseEntity.getBody();
String status = gaoDeResult.getStatus();
if (!status.equals(WeatherConstant.SUCCESS)) {
log.info("Request for Gaode interface failed");
return Collections.emptyList();
}
List<Forecast> forecasts = gaoDeResult.getForecasts();
if (CollectionUtils.isEmpty(forecasts)) {
return Collections.emptyList();
}
// 预报天气
Forecast forecast = forecasts.get(0);
List<WeatherForecast> weatherForecastList = new ArrayList<>();
List<Forecast.Cast> casts = forecast.getCasts();
for (Forecast.Cast cast : casts) {
WeatherForecast weatherForecast = new WeatherForecast();
weatherForecast.setProvince(forecast.getProvince());
weatherForecast.setCity(forecast.getCity());
weatherForecast.setAdcode(forecast.getAdcode());
weatherForecast.setDate(cast.getDate());
weatherForecast.setWeek(cast.getWeek());
weatherForecast.setDayWeather(cast.getDayweather());
weatherForecast.setDayWeatherImg(WeatherType.getCodeByDes(cast.getDayweather()));
weatherForecast.setNightWeather(cast.getNightweather());
weatherForecast.setNightWeatherImg(WeatherType.getCodeByDes(cast.getNightweather()));
weatherForecast.setDayTemp(cast.getDaytemp());
weatherForecast.setNightTemp(cast.getNighttemp());
weatherForecast.setDayWind(cast.getDaywind());
weatherForecast.setNightWind(cast.getNightwind());
weatherForecast.setDayPower(cast.getDaypower());
weatherForecast.setNightPower(cast.getNightpower());
weatherForecast.setReportTime(forecast.getReporttime());
weatherForecastList.add(weatherForecast);
}
return weatherForecastList;
}
}
(四)实体类GaoDeResult
和Forecast
高德地图API返回的数据结构较为复杂,需要定义GaoDeResult
和Forecast
类来接收和处理这些数据。
GaoDeResult
类
java
package com.example.weather.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
@Data
public class GaoDeResult {
private String status;
private String info;
private String infocode;
@JsonProperty("lives")
private List<Live> lives;
@JsonProperty("forecasts")
private List<Forecast> forecasts;
}
Forecast
类
java
package com.example.weather.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
@Data
public class Forecast {
private String province;
private String city;
private String adcode;
private String reporttime;
@JsonProperty("casts")
private List<Cast> casts;
@Data
public static class Cast {
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;
}
}
(五)控制器层
创建WeatherController
类,用于处理前端请求,并调用服务层的方法获取天气数据。
java
package com.example.weather.controller;
import com.example.weather.entity.Live;
import com.example.weather.entity.WeatherForecast;
import com.example.weather.service.WeatherService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/weather")
public class WeatherController {
@Autowired
private WeatherService weatherService;
/**
* 获取实时天气
*
* @param adcode 城市编码
* @return 实时天气数据
*/
@GetMapping("/live")
public Live getLiveWeather(@RequestParam String adcode) {
return weatherService.getLiveWeather(adcode);
}
/**
* 获取未来几天的天气预报
*
* @param adcode 城市编码
* @return 天气预报数据
*/
@GetMapping("/forecast")
public List<WeatherForecast> getForecastWeather(@RequestParam String adcode) {
return weatherService.getForecastWeather(adcode);
}
}
(六)定时任务
为了定期更新天气数据,可以使用Spring的定时任务功能。创建WeatherTask
类,设置定时任务。
java
package com.example.weather.task;
import com.example.weather.entity.Live;
import com.example.weather.entity.WeatherForecast;
import com.example.weather.service.WeatherService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class WeatherTask {
@Autowired
private WeatherService weatherService;
// 每天凌晨3点更新天气数据
@Scheduled(cron = "0 0 3 * * ?")
public void updateWeatherData() {
// 假设我们更新北京的天气数据,北京的城市编码为110000
String adcode = "110000";
// 更新实时天气
Live liveWeather = weatherService.getLiveWeather(adcode);
if (liveWeather != null) {
// 将实时天气数据存储到数据库或缓存中
System.out.println("实时天气数据已更新:" + liveWeather);
}
// 更新未来几天的天气预报
List<WeatherForecast> forecastWeatherList = weatherService.getForecastWeather(adcode);
if (!forecastWeatherList.isEmpty()) {
// 将天气预报数据存储到数据库或缓存中
System.out.println("天气预报数据已更新:" + forecastWeatherList);
}
}
}
(七)工具类WeatherConstant
和WeatherType
为了方便处理天气数据,创建WeatherConstant
类用于定义常量,WeatherType
类用于处理天气类型的映射。
WeatherConstant
类
java
package com.example.weather.common;
public class WeatherConstant {
public static final String SUCCESS = "1";
}
WeatherType
类
java
package com.example.weather.enums;
import lombok.Getter;
public enum WeatherType {
SUNNY("晴", "01"),
CLOUDY("多云", "02"),
OVERCAST("阴", "03"),
LIGHT_RAIN("小雨", "04"),
MODERATE_RAIN("中雨", "05"),
HEAVY_RAIN("大雨", "06"),
STORM("暴雨", "07"),
FOG("雾", "08"),
HAZE("霾", "09"),
SAND("沙尘暴", "10"),
WIND("大风", "11"),
SNOW("雪", "12");
@Getter
private final String description;
@Getter
private final String code;
WeatherType(String description, String code) {
this.description = description;
this.code = code;
}
public static String getCodeByDes(String description) {
for (WeatherType type : WeatherType.values()) {
if (type.getDescription().equals(description)) {
return type.getCode();
}
}
return "";
}
}
四、测试与运行
(一)启动项目
在IDE中运行WeatherApplication
类的main
方法,启动SpringBoot项目。
(二)测试接口
使用Postman或浏览器访问以下接口进行测试:
- 实时天气接口 :
http://localhost:8080/weather/live?adcode=110000
- 天气预报接口 :
http://localhost:8080/weather/forecast?adcode=110000
(三)查看定时任务
查看控制台输出,确认定时任务是否正常运行,天气数据是否按时更新。
五、总结
通过本文的详细步骤,我们成功地在SpringBoot项目中整合了高德地图的天气预报功能。从环境搭建到代码实现,再到定时任务的设置,每一步都清晰明确,确保大家能够按照教程直接上手操作。在实际开发中,可以根据需求进一步优化和扩展功能,例如将天气数据存储到数据库中,或者为用户提供更多城市的天气查询服务。希望本文对大家有所帮助!