<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【項目實踐】接入天氣api在用戶登錄后可以看到當前天氣

      前期調研

      經多方查找,發現和風天氣對于個人開發人相對有好,有詳細的api接口文檔以及實現案例。

      優點:

      • 只需要提供城市、授權ID和Key,就會進行返回 跟天氣相關的多樣態數據;
      • 響應數據種類多,提供各類svg圖標樣式,后續擴展性可以延伸;

      詳情查看官網

      準備工作

      注冊和風天氣賬號

      1. 注冊時需要準備郵箱,手機賬號
      2. 驗證碼注意檢查下垃圾郵件,有可能被默認規則攔截

      1. 添加項目,這里就開始注冊需要使用 的api了

      1. 注冊項目

      1. 創建完成后會顯示這個,下面的憑據 點擊;
      2. api Key 就是我們需要用的APIKey
      3. 詳細設置參照官方文檔進行:

      開發配置

      開始實行

      導入依賴

      1. 返回JSON數據,所以數據格式轉換是必須的,需要jaskson
      2. 和風天氣 API響應的數據使用Gzip壓縮,正常顯示失敗,需要設置 HttpComponentsClientHttpRequestFactory ,為了解決 API 響應壓縮導致的解析問題,確保能夠正確處理和風天氣 API 返回的可能經過 gzip 壓縮的 JSON 數據。
              <!-- Jackson(解析JSON) -->
              <dependency>
                  <groupId>com.fasterxml.jackson.core</groupId>
                  <artifactId>jackson-databind</artifactId>
                  <version>2.13.4.2</version>
              </dependency>
              
              <!-- HttpClient -->
              <dependency>
                  <groupId>org.apache.httpcomponents</groupId>
                  <artifactId>httpclient</artifactId>
                  <version>4.5.13</version>
              </dependency>
      

      bean注入需要掃描的包

      1. 我將所有的外置工具都放到utility中;
      2. 配置RestTemplate(用于發送HTTP請求)
          <!-- 掃描Controller和Service所在的包 -->
          <context:component-scan base-package="com.utility"/>
          
          <!-- 配置RestTemplate(用于發送HTTP請求) -->
          <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"/>
      

      目錄如下:

      配置秘鑰

      public class WeatherConfig {
          // 和風天氣API配置
          public static final String API_URL = "https://devapi.qweather.com/v7/weather/now";
          public static final String API_KEY = "你的密鑰"; // 替換為實際密鑰
          public static final String CITY_ID = "101010100"; // 北京
      }
      

      編寫實體類

      1. 返回顯示的數據,應答代碼所需數據
      // 頂層響應
      public class WeatherResponse {
          private String code;
          private Now now;
          // getter + setter
      }
      
      
      // 當前天氣詳情
      public class Now {
          private String temp;
          private String text;
          private String windDir;
          private String humidity;
          // getter + setter
      }
      

      編寫邏輯層代碼

      1. 調用和風天氣API
      2. 處理數據,符合URL規范,參考官方文檔進行
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;
      import org.springframework.web.client.RestTemplate;
      import com.weather.config.WeatherConfig;
      
      @Service
      public class WeatherService {
      
          @Autowired
          private RestTemplate restTemplate;
      
          // 獲取當前天氣
          public WeatherResponse getCurrentWeather() {
              // 拼接請求URL
              String url = String.format("%s?location=%s&key=%s",
                      WeatherConfig.API_URL,
                      WeatherConfig.CITY_ID,
                      WeatherConfig.API_KEY);
              // 調用API并返回結果
              return restTemplate.getForObject(url, WeatherResponse.class);
          }
      }
      

      控制層代碼

      1. 返回視圖解析器,返回頁面顯示詳情信息
      2. 返回ajax,動態加載頁面,在頁面小地方加載內容
      @Controller
      @RequestMapping("/weather")
      public class WeatherController {
      
          @Autowired
          private WeatherService weatherService;
      
          @Autowired
          private IpParseService ipParseService;
      
          // 響應JSON格式的天氣數據
          @GetMapping("/current/json")
          @ResponseBody // 表示返回JSON而非視圖
          public WeatherResponse getCurrentWeather(HttpServletRequest request) {
              String city = ipParseService.getCityByIp(IpUtils.getRealIp(request));
              WeatherResponse weather = weatherService.getCurrentWeather(city);
              weather.setLocation(city);
              return weather;
          }
      
          @GetMapping("/current")
          public String getCurrentWeather(HttpServletRequest request, Model mode) {
              String city = ipParseService.getCityByIp(IpUtils.getRealIp(request));
              WeatherResponse weather = weatherService.getCurrentWeather(city);
              weather.setLocation(city);
              mode.addAttribute("weather", weather);
              return "weather";
          }
      

      View層視圖顯示

      1. 動態加載的 使用ajax
             $.ajax({
                  url: "/weather/current/json",
                  type: "GET",
                  dataType: "json",
                  success: function (data) {
                      console.log("天氣數據:", data);
                      if (data && data.now !== null) {
                          //     $("#weather_info").text(data.now.text);
                          $("#weather-info").html("天氣:" + data.now.text);
                      }
                  },
                  error: function (xhr, status, error) {
                      console.log("獲取天氣數據失敗:", error);
                      $("#weather-info").html("天氣:獲取失敗");
                  }
              })
      
      1. 視圖跳轉,顯示視圖的內容

      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
      <!DOCTYPE html>
      <html>
      <head>
          <title>當前天氣</title>
          <style>
              .weather-container {
                  width: 500px;
                  margin: 50px auto;
                  padding: 20px;
                  border: 1px solid #ddd;
                  border-radius: 10px;
                  text-align: center;
              }
      
              .weather-info {
                  margin: 20px 0;
                  font-size: 18px;
              }
      
              .temp {
                  font-size: 36px;
                  color: #2c3e50;
                  margin: 10px 0;
              }
      
              .text {
                  font-size: 24px;
                  color: #3498db;
              }
          </style>
      </head>
      <body>
      <div class="weather-container">
          <h2>當前天氣信息</h2>
      
          <!-- 顯示天氣數據 -->
          <c:if test="${not empty weather}">
              <div class="weather-info">
                  <div class="text">${weather.location}</div>
                  <div class="text">${weather.now.text}</div>
                  <div class="temp">${weather.now.temp} ℃</div>
                  <div>風向:${weather.now.windDir}</div>
                  <div>濕度:${weather.now.humidity}%</div>
              </div>
          </c:if>
      
          <!-- 錯誤提示 -->
          <c:if test="${empty weather or weather.code != '200'}">
              <div style="color: red;">獲取天氣失敗,請稍后重試</div>
          </c:if>
      </div>
      </body>
      </html>
      
      

      優化

      優化點1:根據登錄ip判斷所在地,自動使用所在地地點顯示天氣

      1. 工具調查,需要使用獲取地址的api工具
      2. 需要用到api: [https://ip.taobao.com/service/getIpInfo.php](https://ip.taobao.com/service/getIpInfo.php),現在已經永久廢止了,使用[https://ip9.com.cn/get?ip=[IP](https://ip9.com.cn/get?ip=[IP)地址]與前面一樣,都是會返回JSON格式

      控制器

      Controller 改動原來的就可以,畢竟是為了保障以后

      邏輯層

      1. 所需數據少,需要變動點少,索性放在一個里面,引入lombok,省下寫getter/setter;
      2. 城市 是需要請求天氣所需要的東西,如果進行變動的話需要考慮進去
      3. 請求響應失敗的場合 需要返回個默認地址
      package com.utility.service;
      
      import com.utility.config.WeatherConfig;
      import lombok.Data;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;
      import org.springframework.web.client.RestTemplate;
      
      @Service
      public class CityCodeService {
      
          // 和風天氣城市搜索API  curl "https://nj59fbrfwr.re.qweatherapi.com/geo/v2/city/lookup?location=北京&key=key***"
          private static final String CITY_SEARCH_URL = WeatherConfig.API_URL + "/geo/v2/city/lookup";
      
          
          //    @Value("${weather.api.key}")
          //    private String apiKey;
      
          @Autowired
          private RestTemplate restTemplate;
      
          // 根據城市名獲取城市ID(如“北京”→“101010100”)
          public String getCityIdByCityName(String cityName) {
              try {
                  // 拼接請求URL
                  String url = String.format("%s?location=%s&key=%s",
                                             CITY_SEARCH_URL, cityName, WeatherConfig.API_KEY);
      
                  System.out.println(" 和風天氣城市搜索API::" + url);
      
                  // 調用API并解析結果
                  CitySearchResponse response = restTemplate.getForObject(url, CitySearchResponse.class);
      
                  if (response != null && "200".equals(response.getCode())
                      && response.getLocation() != null && !response.getLocation().isEmpty()) {
                      return response.getLocation().get(0).getId(); // 返回第一個匹配的城市ID
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              }
              // 失敗時返回默認城市ID : 北京
              return "101010100";
          }
      
          @Data
          // 城市搜索API返回的實體類(簡化版)
          public static class CitySearchResponse {
              private String code; // 200表示成功
              private java.util.List<Location> location;
          }
      
          @Data
          public static class Location {
              private String id; // 城市ID
          }
      }
      
      
      1. taobao的廢止了,使用了ip9的接口去用;IpParseService返回一個城市name,這個nameCityCodeService需要使用,我們使用這個去 查找城市代碼;
      2. Test 成功,使用junit測試通過,使用的百度在北京的服務器所在的ip地址;使用單元測試的思想,可以避免我們不停的重復啟停服務所花費時間,來回啟動會導致 IDE工具 內存不足;
      package com.utility.service;
      
      import lombok.Data;
      import org.junit.Test;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;
      import org.springframework.web.client.RestTemplate;
      
      @Service
      public class IpParseService {
      
          // 淘寶IP解析接口
      //    private static final String IP_API_URL = "https://ip.taobao.com/service/getIpInfo.php?ip=";
          private static final String IP_API_URL = "https://ip9.com.cn/get?ip=";
      
          @Autowired
          private RestTemplate restTemplate;
      
          // 根據IP獲取城市名稱(如“北京”)
          public String getCityByIp(String ip) {
              try {
                  // 調用淘寶IP接口
                  String url = IP_API_URL + ip;
      
                  // 獲取原始響應作為字符串
      //            String responseString = restTemplate.getForObject(url, String.class);
      
                  IpResponse response = restTemplate.getForObject(url, IpResponse.class);
      
                  // 手動解析JSON(需要引入Jackson或其他JSON庫)
      //            ObjectMapper objectMapper = new ObjectMapper();
      //            IpResponse response = objectMapper.readValue(responseString, IpResponse.class);
      
                  // 解析返回結果(淘寶接口格式特殊,需對應實體類)
                  if (response != null && response.getCode() == 0) {
                      if (response.getData() != null && !response.getData().getCity().isEmpty()) {
                          return response.getData().getCity();
                      }
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              }
              // 解析失敗時返回默認城市
              return "山東";
          }
      
          @Data
          // 淘寶IP接口返回的實體類(簡化版)
          public static class IpResponse {
              private int code; // 0表示成功
              private IpData data;
          }
      
          @Data
          public static class IpData {
              private String city; // 城市名稱
          }
      
          @Test
          public void test() {
              RestTemplate restTemplate = new RestTemplate();
              String IP = "182.61.200.108";
              System.out.println(getCityByIp(IP));
          }
      }
      
      

      工具類

      1. 解析Request中ip地址
      package com.utility.utils;
      
      import javax.servlet.http.HttpServletRequest;
      
      public class IpUtils {
          // 獲取用戶真實IP(考慮代理情況)
          public static String getRealIp(HttpServletRequest request) {
              String ip = request.getHeader("x-forwarded-for");
              if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
                  ip = request.getHeader("Proxy-Client-IP");
              }
              if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
                  ip = request.getHeader("WL-Proxy-Client-IP");
              }
              if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
                  ip = request.getRemoteAddr();
              }
              // 多代理情況下,取第一個IP
              if (ip != null && ip.contains(",")) {
                  ip = ip.split(",")[0].trim();
              }
              return ip;
          }
      }
      

      優化點2:地址拆出來,方便以后使用,這樣就可以一次請求存在Session中使用,節省api請求次數,提高效率

      控制器

      Controller 改動原來的就可以,畢竟是為了保障以后

      邏輯層

      原來功能:

      public WeatherResponse getCurrentWeather(HttpServletRequest request) {
      
      String cityId =
      cityCodeService
      .getCityIdByCityName(ipParseService
                           .getCityByIp(IpUtils.getRealIp(request)));
      
      }
      

      分析可拆分點,IP轉化日期單獨拿出,后面再單獨去調用;

      public WeatherResponse getCurrentWeather(String city) {
          String cityId = cityCodeService.getCityIdByCityName(city);
      }
      

      實體類

      需求發生變化,頁面內容就要變更,取值的方式就多種多樣了,改之前的Entity,返回的ResponseVo中加個字段? 再新寫個實體類? 把IpParseServiceIpData提取出來?思路各色各樣

      人世間萬事萬物都是變得,唯唯物辯證法永恒。

      posted @ 2025-08-04 22:07  柯基大大  閱讀(8)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 六十路熟妇乱子伦| 亚洲V天堂V手机在线| 欧美国产日韩久久mv| AV无码不卡一区二区三区| 国产在线观看免费观看不卡| 噜噜综合亚洲av中文无码| 成人精品区| 亚洲av日韩av永久无码电影| 日本韩无专砖码高清观看| 亚洲精品区午夜亚洲精品区| 国产午夜福利精品视频| 亚洲婷婷六月的婷婷| 日韩精品人妻中文字幕| 亚洲熟女精品一区二区| 中文字幕av一区二区| 日韩乱码人妻无码中文字幕视频| 国产成人精品18| 麻豆一区二区三区蜜桃免费| 国产 另类 在线 欧美日韩| 公天天吃我奶躁我的在线观看| 久久一日本综合色鬼综合色 | 亚洲五月丁香综合视频| 天堂mv在线mv免费mv香蕉| 又色又爽又黄18禁美女裸身无遮挡| 亚洲精品国产美女久久久| 日本一区二区三区四区黄色| 狠狠躁夜夜躁人人爽天天bl| 人妻一区二区三区三区| 国产在线视频不卡一区二区| 国产精品成人免费视频网站京东| 亚洲欧美日韩国产精品专区| 亚洲高清aⅴ日本欧美视频| 国产成AV人片久青草影院| 亚洲色成人网站www永久男男| 黑人强伦姧人妻久久| 国内精品自线在拍| av大片在线无码免费| 日韩一区二区三区无码a片| 精品国产一区二区三区av性色| 男女18禁啪啪无遮挡激烈网站| 亚洲爆乳少妇无码激情|