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

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

一、前言

在当今数字化时代,天气预报功能在众多应用中扮演着重要角色。通过整合高德地图提供的天气API,我们可以轻松地在自己的SpringBoot项目中实现这一功能,为用户提供实时和未来几天的天气信息。本文将详细介绍如何在SpringBoot项目中整合高德地图的天气预报功能,包括环境搭建、代码实现、定时任务设置等关键步骤,确保大家能够按照教程成功实现功能。

二、环境搭建

(一)创建SpringBoot项目

  1. 使用Spring Initializr

    • 访问 Spring Initializr 网站。
    • 选择项目元数据,如项目名称、包名等。
    • 添加依赖:Spring WebSpring Boot DevTools(可选,方便开发时热部署)。
    • 点击"Generate"按钮下载项目压缩包,解压后导入到你的IDE(如IntelliJ IDEA或Eclipse)中。
  2. 项目结构示例

    arduino 复制代码
    spring-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申请

  1. 注册高德开放平台账号

    • 访问 高德开放平台 官网,注册账号并登录。
    • 在"控制台"中创建应用,获取API Key。该Key将用于后续调用高德地图的天气API。
  2. 配置application.yml

    • 将获取到的API Key和天气API的URL配置到application.yml文件中。
    yaml 复制代码
    amap-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;
}

(二)实体类

定义两个实体类LiveWeatherForecast,分别用于存储实时天气和预报天气的数据。

实时天气实体类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;
    }
}

(四)实体类GaoDeResultForecast

高德地图API返回的数据结构较为复杂,需要定义GaoDeResultForecast类来接收和处理这些数据。

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);
        }
    }
}

(七)工具类WeatherConstantWeatherType

为了方便处理天气数据,创建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项目中整合了高德地图的天气预报功能。从环境搭建到代码实现,再到定时任务的设置,每一步都清晰明确,确保大家能够按照教程直接上手操作。在实际开发中,可以根据需求进一步优化和扩展功能,例如将天气数据存储到数据库中,或者为用户提供更多城市的天气查询服务。希望本文对大家有所帮助!

相关推荐
MAGICIAN...10 分钟前
【java-软件设计原则】
java·开发语言
Ticnix10 分钟前
ECharts初始化、销毁、resize 适配组件封装(含完整封装代码)
前端·echarts
纯爱掌门人14 分钟前
终焉轮回里,藏着 AI 与人类的答案
前端·人工智能·aigc
砍材农夫15 分钟前
threadlocal
后端
JH307316 分钟前
为什么switch不支持long
java
twl17 分钟前
OpenClaw 深度技术解析
前端
崔庆才丨静觅21 分钟前
比官方便宜一半以上!Grok API 申请及使用
前端
星光不问赶路人29 分钟前
vue3使用jsx语法详解
前端·vue.js
神奇小汤圆31 分钟前
告别手写HTTP请求!Spring Feign 调用原理深度拆解:从源码到实战,一篇搞懂
后端
天蓝色的鱼鱼32 分钟前
shadcn/ui,给你一个真正可控的UI组件库
前端