Spring Boot实现一个天气预报系统(一)
1.數據來源
-
天氣的數據來源為中華萬年歷
通過城市名稱獲得天氣數據:http://wthrcdn.etouch.cn/weather_mini?city=北京
通過城市id獲得天氣數據:http://wthrcdn.etouch.cn/weather_mini?citykey=101280601
-
城市id列表
每個城市都有一個唯一的id作為標識:https://waylau.com/data/citylist.xml
-
這里已北京為例,可以看到如下天氣數據返回
2.開發環境
-
JDK8
-
Maven
-
Spring Boot Web Starter 2.1.6
-
Apache HttpClient 4.5.3
3.初始化一個Spring Boot項目
(1)添加maven依賴
? ? ? ?<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.0</version><scope>provided</scope></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.3</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency> ?<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>5.1.7.RELEASE</version><scope>compile</scope></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.8</version><scope>compile</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>(2)創建實體類
@Data public class Weather implements Serializable {private String city;private String aqi;private String wendu;private String ganmao;private Yesterday yesterday;private List<Forecast> forecast; } @Data public class Forecast implements Serializable {private String date;private String high;private String fengxiang;private String low;private String fengli;private String type; } @Data public class Yesterday implements Serializable {private String date;private String high;private String fx;private String low;private String fl;private String type; } @Data public class WeatherResponse implements Serializable {/*** 消息數據*/private Weather data;/*** 消息狀態*/private String status;/*** 消息描述*/private String desc; }(3)服務接口及實現
public interface WeatherDataService { ?/*** 根據城市id來查詢天氣數據** @param cityId* @return*/WeatherResponse getDataByCityId(String cityId); ?/*** 根據城市名稱來查詢天氣數據** @param cityName* @return*/WeatherResponse getDataByCityName(String cityName); } @Service public class WeatherDataServiceImpl implements WeatherDataService {@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate StringRedisTemplate stringRedisTemplate;private final Logger logger = LoggerFactory.getLogger(WeatherDataServiceImpl.class);private final String WEATHER_API = "http://wthrcdn.etouch.cn/weather_mini";/*** 緩存超時時間*/private final Long TIME_OUT = 1800L; ?@Overridepublic WeatherResponse getDataByCityId(String cityId) {String uri = WEATHER_API + "?citykey=" + cityId;return this.doGetWeatherData(uri);} ?@Overridepublic WeatherResponse getDataByCityName(String cityName) {String uri = WEATHER_API + "?city=" + cityName;return this.doGetWeatherData(uri);} ?private WeatherResponse doGetWeatherData(String uri) {ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();//將調用的uri作為緩存的keyString strBody = null;//先查緩存,沒有找到查服務if (!stringRedisTemplate.hasKey(uri)) {logger.info("未找到 key " + uri); ?ResponseEntity<String> response = restTemplate.getForEntity(uri, String.class);if (response.getStatusCodeValue() == 200) {strBody = response.getBody();}ops.set(uri, strBody, TIME_OUT, TimeUnit.SECONDS);} else {logger.info("找到 key " + uri + ",value=" + ops.get(uri));strBody = ops.get(uri);}ObjectMapper mapper = new ObjectMapper();WeatherResponse weather = null;try {weather = mapper.readValue(strBody, WeatherResponse.class);} catch (IOException e) {e.printStackTrace();}return weather;} }(4)控制層類
@RestController @RequestMapping("/weather") public class WeatherController {@Autowiredprivate WeatherDataService weatherDataService; ?@GetMapping("/cityId/{cityId}")public WeatherResponse getReportByCityId(@PathVariable("cityId") String cityId) {return weatherDataService.getDataByCityId(cityId);} ?@GetMapping("/cityName/{cityName}")public WeatherResponse getReportByCityName(@PathVariable("cityName") String cityName) {return weatherDataService.getDataByCityName(cityName);} }(5)配置類
@Configuration public class Config {@Beanpublic RestTemplate restTemplate(RestTemplateBuilder builder) {// Do any additional configuration herereturn builder.build();} }(6)Spring配置文件
spring:redis:host: 127.0.0.1database: 0password:port: 63794.為什么使用Redis
緩存的使用與系統的時效性有著非常大的關系。當所使用的系統時效性要求不高時,選擇使用緩存是極好的。當系統要求的時效性比較高時,則并不適合使用緩存。
天氣數據接口,本身時效性并不是很高,而且又因為時Web服務,在調用過程中,是存在延時的。所以,采用緩存,一方面可以有效減輕訪問天氣接口服務帶來的延時問題;另一方面也可以減輕天氣接口的負擔,提高并發訪問量。
特別是使用第三方免費的天氣API,這些API往往對用戶的調用次數及頻率有一定的限制。所以為了減輕天氣API提供方的負荷,并不需要去實時調用其第三方接口。
由于天氣數據更新頻率的特點(基本上一個小時或半個小時更新一次),因此,在redis中設置了30分鐘的失效時間。
5.測試和運行
1.啟動Spring Boot項目,啟動redis
2.訪問接口:http://localhost:8080/weather/cityName/太原,日志如下
未找到 key http://wthrcdn.etouch.cn/weather_mini?city=太原3.再次訪問上面的接口,日志如下
找到 key http://wthrcdn.etouch.cn/weather_mini?city=太原,value={"data":{"yesterday":{"date":"26日星期三","high":"高溫 32℃","fx":"東北風","low":"低溫 20℃","fl":"<![CDATA[<3級]]>","type":"多云"},"city":"太原","forecast":[{"date":"27日星期四","high":"高溫 28℃","fengli":"<![CDATA[<3級]]>","low":"低溫 18℃","fengxiang":"北風","type":"小雨"},{"date":"28日星期五","high":"高溫 32℃","fengli":"<![CDATA[<3級]]>","low":"低溫 16℃","fengxiang":"東北風","type":"多云"},{"date":"29日星期六","high":"高溫 32℃","fengli":"<![CDATA[<3級]]>","low":"低溫 15℃","fengxiang":"西北風","type":"晴"},{"date":"30日星期天","high":"高溫 30℃","fengli":"<![CDATA[<3級]]>","low":"低溫 16℃","fengxiang":"北風","type":"晴"},{"date":"1日星期一","high":"高溫 31℃","fengli":"<![CDATA[<3級]]>","low":"低溫 15℃","fengxiang":"東南風","type":"多云"}],"ganmao":"相對今天出現了較大幅度降溫,較易發生感冒,體質較弱的朋友請注意適當防護。","wendu":"27"},"status":1000,"desc":"OK"}?
?
總結
以上是生活随笔為你收集整理的Spring Boot实现一个天气预报系统(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 枚举类的使用-使用实例域来替代序数
- 下一篇: Spring Boot实现一个天气预报系