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

简介: 本文介绍了如何在SpringBoot项目中整合高德地图API实现天气预报功能。从创建SpringBoot项目、配置依赖和申请高德地图API开始,详细讲解了实体类设计、服务层实现(调用高德地图API获取实时与预报天气数据)、控制器层接口开发以及定时任务的设置。通过示例代码,展示了如何获取并处理天气数据,最终提供实时天气与未来几天天气预报的接口。文章还提供了测试方法及运行步骤,帮助开发者快速上手并扩展功能。

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

一、前言

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

二、环境搭建

(一)创建SpringBoot项目

  1. 使用Spring Initializr

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

    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和定时任务等功能。

<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文件中。
      amap-weather-config:
      weatherurl: https://restapi.amap.com/v3/weather/weatherInfo
      key: YOUR_API_KEY
      

三、代码实现

(一)配置类

创建一个配置类AmapWeatherConfig,用于读取application.yml中的高德地图天气API配置。

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

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

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,并将返回的数据封装到实体类中。

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

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

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类,用于处理前端请求,并调用服务层的方法获取天气数据。

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类,设置定时任务。

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

package com.example.weather.common;

public class WeatherConstant {
   
    public static final String SUCCESS = "1";
}

WeatherType

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

相关文章
|
1月前
|
XML 前端开发 Java
SpringBoot实现文件上传下载功能
本文介绍了如何使用SpringBoot实现文件上传与下载功能,涵盖配置和代码实现。包括Maven依赖配置(如`spring-boot-starter-web`和`spring-boot-starter-thymeleaf`)、前端HTML页面设计、WebConfig路径映射配置、YAML文件路径设置,以及核心的文件上传(通过`MultipartFile`处理)和下载(利用`ResponseEntity`返回文件流)功能的Java代码实现。文章由Colorful_WP撰写,内容详实,适合开发者学习参考。
100 0
|
5天前
|
安全 Java API
Spring Boot 功能模块全解析:构建现代Java应用的技术图谱
Spring Boot不是一个单一的工具,而是一个由众多功能模块组成的生态系统。这些模块可以根据应用需求灵活组合,构建从简单的REST API到复杂的微服务系统,再到现代的AI驱动应用。
113 7
|
1月前
|
SQL 前端开发 Java
深入理解 Spring Boot 项目中的分页与排序功能
本文深入讲解了在Spring Boot项目中实现分页与排序功能的完整流程。通过实际案例,从Service层接口设计到Mapper层SQL动态生成,再到Controller层参数传递及前端页面交互,逐一剖析每个环节的核心逻辑与实现细节。重点包括分页计算、排序参数校验、动态SQL处理以及前后端联动,确保数据展示高效且安全。适合希望掌握分页排序实现原理的开发者参考学习。
78 4
|
7月前
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
114 4
|
7月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
394 1
|
6月前
|
Java 开发者 微服务
手写模拟Spring Boot自动配置功能
【11月更文挑战第19天】随着微服务架构的兴起,Spring Boot作为一种快速开发框架,因其简化了Spring应用的初始搭建和开发过程,受到了广大开发者的青睐。自动配置作为Spring Boot的核心特性之一,大大减少了手动配置的工作量,提高了开发效率。
115 0
|
7月前
|
Java API 数据库
Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐
本文通过在线图书管理系统案例,详细介绍如何使用Spring Boot构建RESTful API。从项目基础环境搭建、实体类与数据访问层定义,到业务逻辑实现和控制器编写,逐步展示了Spring Boot的简洁配置和强大功能。最后,通过Postman测试API,并介绍了如何添加安全性和异常处理,确保API的稳定性和安全性。
109 0
|
6月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
230 62
|
6月前
|
消息中间件 缓存 Java
手写模拟Spring Boot启动过程功能
【11月更文挑战第19天】Spring Boot自推出以来,因其简化了Spring应用的初始搭建和开发过程,迅速成为Java企业级应用开发的首选框架之一。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,帮助读者深入理解其工作机制。
88 3
|
6月前
|
前端开发 Java easyexcel
SpringBoot操作Excel实现单文件上传、多文件上传、下载、读取内容等功能
SpringBoot操作Excel实现单文件上传、多文件上传、下载、读取内容等功能
336 8