From 1ae63df5de1e2357dddf4b2109aee7859bb4facc Mon Sep 17 00:00:00 2001 From: NagoColer Date: Fri, 6 Oct 2023 13:37:54 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E8=AE=BA=E5=9D=9B=E9=A6=96?= =?UTF-8?q?=E9=A1=B5=E4=BB=A5=E5=8F=8A=E5=A4=A9=E6=B0=94=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=AF=B9=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/config/WebConfiguration.java | 6 ++ .../example/controller/ForumController.java | 25 ++++++ .../example/entity/vo/response/WeatherVO.java | 12 +++ .../com/example/service/WeatherService.java | 7 ++ .../service/impl/WeatherServiceImpl.java | 84 +++++++++++++++++++ .../src/main/resources/application-dev.yml | 2 + .../src/main/resources/application-prod.yml | 2 + my-project-frontend/index.html | 4 + .../src/components/Weather.vue | 53 ++++-------- .../src/views/forum/TopicList.vue | 36 +++++++- 10 files changed, 190 insertions(+), 41 deletions(-) create mode 100644 my-project-backend/src/main/java/com/example/controller/ForumController.java create mode 100644 my-project-backend/src/main/java/com/example/entity/vo/response/WeatherVO.java create mode 100644 my-project-backend/src/main/java/com/example/service/WeatherService.java create mode 100644 my-project-backend/src/main/java/com/example/service/impl/WeatherServiceImpl.java diff --git a/my-project-backend/src/main/java/com/example/config/WebConfiguration.java b/my-project-backend/src/main/java/com/example/config/WebConfiguration.java index 991163b..ccd70ca 100644 --- a/my-project-backend/src/main/java/com/example/config/WebConfiguration.java +++ b/my-project-backend/src/main/java/com/example/config/WebConfiguration.java @@ -4,6 +4,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.web.client.RestTemplate; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** @@ -12,6 +13,11 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfiguration implements WebMvcConfigurer { + @Bean + public RestTemplate restTemplate(){ + return new RestTemplate(); + } + @Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); diff --git a/my-project-backend/src/main/java/com/example/controller/ForumController.java b/my-project-backend/src/main/java/com/example/controller/ForumController.java new file mode 100644 index 0000000..64a75a0 --- /dev/null +++ b/my-project-backend/src/main/java/com/example/controller/ForumController.java @@ -0,0 +1,25 @@ +package com.example.controller; + +import com.example.entity.RestBean; +import com.example.entity.vo.response.WeatherVO; +import com.example.service.WeatherService; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +//论坛相关接口都在这里 +@RestController +@RequestMapping("/api/forum") +public class ForumController { + + @Resource + WeatherService service; + + @GetMapping("/weather") + public RestBean weather(double latitude, double longitude){ + WeatherVO weatherVO = service.fetchWeather(latitude, longitude); + return weatherVO != null ? + RestBean.success(weatherVO) : RestBean.failure(400, "获取地理位置信息失败!"); + } +} diff --git a/my-project-backend/src/main/java/com/example/entity/vo/response/WeatherVO.java b/my-project-backend/src/main/java/com/example/entity/vo/response/WeatherVO.java new file mode 100644 index 0000000..fe69c42 --- /dev/null +++ b/my-project-backend/src/main/java/com/example/entity/vo/response/WeatherVO.java @@ -0,0 +1,12 @@ +package com.example.entity.vo.response; + +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import lombok.Data; + +@Data +public class WeatherVO { + JSONObject now; + JSONObject location; + JSONArray hourly; +} diff --git a/my-project-backend/src/main/java/com/example/service/WeatherService.java b/my-project-backend/src/main/java/com/example/service/WeatherService.java new file mode 100644 index 0000000..eeb45b3 --- /dev/null +++ b/my-project-backend/src/main/java/com/example/service/WeatherService.java @@ -0,0 +1,7 @@ +package com.example.service; + +import com.example.entity.vo.response.WeatherVO; + +public interface WeatherService { + WeatherVO fetchWeather(double latitude, double longitude); +} diff --git a/my-project-backend/src/main/java/com/example/service/impl/WeatherServiceImpl.java b/my-project-backend/src/main/java/com/example/service/impl/WeatherServiceImpl.java new file mode 100644 index 0000000..dda638d --- /dev/null +++ b/my-project-backend/src/main/java/com/example/service/impl/WeatherServiceImpl.java @@ -0,0 +1,84 @@ +package com.example.service.impl; + +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.example.entity.vo.response.WeatherVO; +import com.example.service.WeatherService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import java.util.zip.GZIPInputStream; + +@Slf4j +@Service +public class WeatherServiceImpl implements WeatherService { + + @Resource + StringRedisTemplate template; + + @Resource + RestTemplate rest; + + @Value("${spring.weather.key}") + String key; + + @Override + public WeatherVO fetchWeather(double latitude, double longitude) { + return fetchFromCache(latitude, longitude); + } + + private WeatherVO fetchFromCache(double latitude, double longitude) { + JSONObject geo = this.decompressStringToJSON(rest.getForObject( + "https://geoapi.qweather.com/v2/city/lookup?location="+longitude+","+latitude+"&key="+key, byte[].class)); + if(geo == null) return null; + JSONObject location = geo.getJSONArray("location").getJSONObject(0); + int id = location.getInteger("id"); + String key = "weather:"+id; + String cache = template.opsForValue().get(key); + if(cache != null) + return JSONObject.parseObject(cache).to(WeatherVO.class); + WeatherVO weather = this.fetchFromAPI(id, location); + if(weather == null) + return null; + template.opsForValue().set(key, JSONObject.from(weather).toJSONString(), 1, TimeUnit.HOURS); + return weather; + } + + private WeatherVO fetchFromAPI(int id, JSONObject location) { + WeatherVO vo = new WeatherVO(); + vo.setLocation(location); + JSONObject now = this.decompressStringToJSON(rest.getForObject( + "https://devapi.qweather.com/v7/weather/now?location="+id+"&key="+key, byte[].class)); + if(now == null) return null; + vo.setNow(now.getJSONObject("now")); + JSONObject hourly = this.decompressStringToJSON(rest.getForObject( + "https://devapi.qweather.com/v7/weather/24h?location="+id+"&key="+key, byte[].class)); + if(hourly == null) return null; + vo.setHourly(new JSONArray(hourly.getJSONArray("hourly").stream().limit(5).toList())); + return vo; + } + + private JSONObject decompressStringToJSON(byte[] data) { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + try { + GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(data)); + byte[] buffer = new byte[1024]; + int bytesRead; + while ((bytesRead = gis.read(buffer)) != -1) + stream.write(buffer, 0, bytesRead); + gis.close(); + stream.close(); + } catch (IOException ignored) { + return null; + } + return JSONObject.parseObject(stream.toString()); + } +} diff --git a/my-project-backend/src/main/resources/application-dev.yml b/my-project-backend/src/main/resources/application-dev.yml index 358fa6d..c0b5e18 100644 --- a/my-project-backend/src/main/resources/application-dev.yml +++ b/my-project-backend/src/main/resources/application-dev.yml @@ -43,3 +43,5 @@ spring: endpoint: 'http://localhost:9000' username: 'minio' password: 'password' + weather: + key: 7abbc24d3b4443b597a3b3c676e0f221 diff --git a/my-project-backend/src/main/resources/application-prod.yml b/my-project-backend/src/main/resources/application-prod.yml index 4498287..993c709 100644 --- a/my-project-backend/src/main/resources/application-prod.yml +++ b/my-project-backend/src/main/resources/application-prod.yml @@ -47,3 +47,5 @@ spring: endpoint: 'http://localhost:9000' username: 'minio' password: 'password' + weather: + key: 7abbc24d3b4443b597a3b3c676e0f221 diff --git a/my-project-frontend/index.html b/my-project-frontend/index.html index e015332..37a47d5 100644 --- a/my-project-frontend/index.html +++ b/my-project-frontend/index.html @@ -10,6 +10,10 @@ diff --git a/my-project-frontend/src/components/Weather.vue b/my-project-frontend/src/components/Weather.vue index a852a4b..d851a93 100644 --- a/my-project-frontend/src/components/Weather.vue +++ b/my-project-frontend/src/components/Weather.vue @@ -1,59 +1,34 @@