1. 首页
  2. >
  3. 编程技术
  4. >
  5. Java

大牛教大家如何用SpringBoot技术快速实现天气预报系统

从一个天气预报系统讲起

本节通过Spring Boot技术快速实现一个天气预报系统。

通过这个系统,一方面可以了解Spring Boot的全面用法,为后续创建微服务应用打下基础;另一方面,该系统会作为本节进行微服务架构改造的非常好的起点。

下面以前面创建的hello-world应用作为基础进行改造,成为新的应用micro-weather-basic。

大牛教大家如何用SpringBoot技术快速实现天气预报系统


开发环境

为了演示本例,需要采用如下开发环境。

. JDK8。

.Gradle 4.0。

. Spring Boot Web Starter 2.0.0.M4。

Apache HttpClient 4.5.3。

数据来源

天气的数据是天气预报的实现基础。本应用与实际的天气数据无关,理论上可以兼容多种数据来源。但为求简单,我们在网上找了一个免费、可用的天气数据接口。

  • ·天气数据来源为中华万年历。例如以下两种方式。

通过城市名称获得天气数据: http://wthrcdn.etouch.cn/weather_mini?city=深圳。

通过城市ID获得天气数据: http://wthrcdn.etouch.cn/weather_mini?citykey=101280601。

  • ·城市ID列表。每个城市都有一个唯一的ID作为标识,见https:/waylau.com/data/citylist.xml。

调用天气服务接口示例,这里以“深圳”城市为例,可看到如下天气数据返回。

{ "data":{ "yesterday":{ "date" :"1日星期五""high" :"高温33℃", "fx":"无持续风向""low" :"低温26℃", "fl":"<![CDATA[<3级]]>", "type":"多云" }, "city":"深圳""aqi" : "72", "forecast":[ "date":"2日星期六""high":"高温32℃", "fengli":"<![CDATA[<3级]1>""low" :"低温26℃", "fengxiang":"无持续风向""type" :"阵雨" }, "date":"3日星期天""high":"高温 29℃", "fengli":"<![CDATA[5-6级]1>", "low" :"低温26℃", "fengxiang":"无持续风向""type":"大雨" "date":"4日星期一""high":"高温29℃", "fengli":"<![CDATA[3-4级]1>", "low":"低温26℃""fengxiang" :"西南风""type":"暴雨" }, "date":"5日星期二""high":"高温31℃", "fengli":"<![CDATA[<3级]]>", "low":"低温27℃""fengxiang":"无持续风向""type":"阵雨" "date" :"6日星期三""high":"高温32℃", "fengli":"<![CDATA[<3级]l>", "low":"低温27℃", "fengxiang" :"无持续风向""type":"阵雨"  } "ganmao":"风较大,阴冷潮湿,较易发生感冒,体质较弱的朋友请注意适当防护。 " wendu":"29" }, "status": 1000, "desc":"OK"} 

通过观察以上数据,来理解每个返回字段的含义。

  • “city”:城市名称。
  • "aqi”:空气指数。
  • “wendu”:实时温度。
  • “date”:日期,包含未来5天。
  • “high”:最高温度。
  • “low”:最低温度。
  • “fengli”:风力。
  • “fengxiang”:风向。
  • “type”:天气类型。

以上数据是需要的天气数据的核心数据,但是,同时也要关注下面两个字段。

  • “status”:接口调用的返回状态,返回值“1000”,意味着数据接口正常。
  • ·“desc”:接口状态的描述,“OK”代表接口正常。

重点关注返回值不是“1000”的情况,这说明这个接口调用异常。

初始化一个Spring Boot项目

初始化一个Spring Boot项目“micro-weather-basic”,该项目可以直接以之前的“hello-world"应用作为基础进行修改。

添加Apache HttpClient的依赖,来作为Web请求的客户端。完整的依赖情况如下。

//依赖关系 dependencies { //该依赖用于编译阶段 compile('org.springframework.boot:spring-boot-starter-web') /添加Apache HttpClient依赖 compile('org.apache.httpcomponents:httpclient:4.5.3') //该依赖用于测试阶段 testCompile('org.springframework.boot:spring-boot-starter-test')}


大牛教大家如何用SpringBoot技术快速实现天气预报系统

创建天气信息相关的值对象

创建com.waylau.spring.cloud.weather.vo包,用于存放相关值对象。这些对象都是POJO对象,没有复杂的业务逻辑

创建天气信息类 Weather:

public class Weather implements Serializable { private static final long serialVersionUID - 1L; private string city; private String aqi; private String wendu; private string ganmao; private Yesterday yesterday; private List<Forecast>forecast; 1/省略getter/setter方法 }

昨日天气信息类Yesterday :

public class Yesterday implements Serializable { private static final long serialversionUID = 1L; private string date; private string high; private String fx; private String low; private String fl; private String type; //省略getter/setter方法 }

未来天气信息类Forecast:

public class Forecast implements Serializable  private static final long serialVersionUID =1L; private string date; private string high; private string fengxiang; private string low; private String fengli; private String type; //省略getter/setter方法 }

WeatherResponse作为整个消息的返回对象:

public class WeatherResponse implements Serializable{ private static final long serialversionUID =1L; private Weather data;1/消息数据 private String status;//消息状态 private string desc;/l消息描述 //省略getter/setter方法 }

服务接口及实现

创建com.waylau.spring.cloud.weather.service包,用于存放服务接口及其实现。

下面是定义服务的两个接口方法,一个是根据城市的ID来查询天气数据,另一个是根据城市名称来查询天气数据。

package com.waylau.spring.cloud.weather.service; import com.waylau.spring.cloud.weather.vo.WeatherResponse; /*★ *天气数据服务. 大 csince 1.0.o 2017年10月18日 *  @author <a href="https://waylau.com">Way Lau</a> */ public interface weatherDataservice { /** 根据城市ID来查询天气数据 * *@param city工d *return */ WeatherResponse getDataByCityId(String cityId); /** *根据城市名称来查询天气数据 * *@param cityId *@return */ WeatherResponse getDataByCityName(String cityName); }

其服务实现WeatherDataServiceImpl为:

package com.waylau.spring.cloud.weather.service; import java.io.IOException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import com.fasterxml.jackson.databind.0bjectMapper; import com.waylau.spring.cloud.weather.vo.WeatherResponse; /** *天气数据服务. * * @since 1.0.0 2017年10月18日 * @author <a href="https://waylau.com">Way Lau</a> */ @service public class WeatherDataServiceImpl implements WeatherDataService { Autowired private RestTemplate restTemplate; private final string WEATHER_API = "http://wthrcdn.etouch.cn/weath- er_ mini"; @override public WeatherResponse getDataByCityId(string cityId){ String uri = WEATHER_API + "?citykey=" + cityId; return this.doGetweatherData(uri); } @override public WeatherResponse getDataByCityName(String cityName){ String uri = WEATHER_API +"?city=" + cityName; return this.doGetWeatherData (uri); private WeatherResponse doGetWeatherData(String uri){ ResponseEntity<String> response = restTemplate.getForEntity(uri, String.class); String strBody = null; if(response.getstatusCodevalue()==200){ strBody= response.getBody(; } objectMapper mapper = new objectMapper(); WeatherResponse weather = null; try{ weather = mapper.readValue (strBody,WeatherResponse.class); }catch (工OException e{ e.printStackTrace(); return weather;

其中:

. RestTemplate是一个REST客户端,默认采用Apache HttpClient来实现;

·返回的天气信息采用了Jackson来进行反序列化,使其成为WeatherResponse对象。

控制器层

创建com.waylau.spring.cloud.weather.service包,用于存放控制器层代码。控制器层暴露了RESTful API接口。

package com.waylau.spring.cloud.weather.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping: import org.springframework.web.bind.annotation.RestController; import com.waylau.spring.cloud.weather.service.WeatherDataService; import com.waylau.spring.cloud.weather.vo.WeatherResponse; /★大 *天气AP工. * * @since 1.0.0 20171018日 * author <a href="https://waylau.com">Way Lau</a> */ @RestController RequestMapping("/weather") public class WeatherController { @Autowired private WeatherDataService weatherDataService; @GetMapping("/cityId/{cityId}") public WeatherResponse getReportByCityId(CPathVariable("cityId") string cityId){ return weatherDataService.getDataByCityId(cityId); } GetMapping("/cityName/{cityName}") public WeatherResponse getReportByCityName (CPathVariable ("cityName") string cityName){ return weatherDataService.getDataByCityName(cityName);}

其中,@RestController会自动将返回的数据进行序列化,使其成为JSON数据格式。

配置类

创建com.waylau.spring.cloud.weather.config包,用于存放配置相关的代码。创建RestConfiguration

类,该类是RestTemplate 的配置类。

package com.waylau.spring.cloud.weather.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; /** *REST 配置类. * *@since 1.0.02017年10月18日 * @author <a href="https://waylau.com" >Way Lau</a> */ Configuration public class RestConfiguration { Autowired private RestTemplateBuilder builder; @Bean public RestTemplate restTemplate({ return builder .build();} }

访问API

运行项目之后,访问以下API来进行测试。

  • . http://localhost:8080/weather/cityId/101280601。
  • http://localhost:8080/weather/cityName/惠州。

能看到如图6-1所示的天气API返回的数据。

大牛教大家如何用SpringBoot技术快速实现天气预报系统

本篇内容给大家讲解的是:通过SpringBoot技术快速实现一个天气预报系统