前言
本系列文章將簡單的學習SpringCloud微服務相關知識,其實也是因爲時間的原因,一直拖到現在,遂打算趁着假期,決定記錄下來。
從天氣預報微服務系統的單體架構——>分佈式架構的演變過程中,一步一步,由淺及深的學習SpringCloud微服務的思想與其實現的組件。
本系列文章分爲以下幾個章節:
- SpringBoot搭建天氣預報微服務系統(單體架構)
- SpringBoot集成Redis緩存
- SpringBoot集成Quartz定時框架
- SpringBoot結合Thymeleaf模板與Bootstrap快速搭建界面
- 單體架構到微服務架構的拆分
- SpringCloud微服務組件—Eureka服務註冊與發現
- SpringCloud微服務組件—Feign負載均衡與高可用
- SpringCloud微服務組件—Zuul實現API網關分配
- SpringCloud微服務組件—Config集中實現配置管理
- SpringCloud微服務組件—Hystrix服務熔斷機制
項目源碼已上傳至Github.
開發環境
- JDK 1.8
- IDEA 2017.3
- Gradle 4
- HttpClient 4.5.3
- SpringBoot 2.0.0.RELEASE
//依賴關係
dependencies {
//該依賴用於編譯階段
compile('org.springframework.boot:spring-boot-starter-web')
//HttpClient
compile('org.apache.httpcomponents:httpclient:4.5.3')
//該依賴用於測試階段
testCompile('org.springframework.boot:spring-boot-starter-test')
}
開發需求
天氣預報項目的功能特別簡單。即用戶可以通過城市名稱查詢對應的城市天氣。
關於天氣預報數據的來源
我們使用網上免費的第三方天氣API服務提供商。當然對於的缺點就是不穩定,隨時可能掛掉,但是足以應付我們的開發學習。
開發過程
項目結構
從返回JSON數據建立對應的實體類
我們利用Postman發送天氣請求。
http://wthrcdn.etouch.cn/weather_mini?citykey=101280101
返回數據如下(部分):
{
"data": {
"yesterday": {
"date": "27日星期五",
"high": "高溫 26℃",
"fx": "無持續風向",
"low": "低溫 22℃",
"fl": "<![CDATA[<3級]]>",
"type": "陣雨"
},
"city": "廣州",
"aqi": "77",
"forecast": [
{
"date": "28日星期六",
"high": "高溫 26℃",
"fengli": "<![CDATA[<3級]]>",
"low": "低溫 21℃",
"fengxiang": "無持續風向",
"type": "陣雨"
},
{
"date": "29日星期天",
"high": "高溫 27℃",
"fengli": "<![CDATA[<3級]]>",
"low": "低溫 23℃",
"fengxiang": "無持續風向",
"type": "陣雨"
}
],
"ganmao": "各項氣象條件適宜,無明顯降溫過程,發生感冒機率較低。",
"wendu": "24"
},
"status": 1000,
"desc": "OK"
}
可以很容易的發現,可以建立四個實體類。
- Forecast
private String date;
private String high;
private String fengli;
private String low;
private String fengxiang;
private String type;
- Weather
private Yesterday yesterday;
private String city;
private String aqi;
private List<Forecast> forecast;
private String ganmao;
private String wendu;
- WeatherResponse
private Weather data;
private Integer status;
private String desc;
- Yesterday
private String date;
private String high;
private String fx;
private String low;
private String fl;
private String type;
建立天氣預報系統API
對於系統,我們只提供兩個請求方式。
- 根據城市ID查詢天氣 /cityId/{cityId}
- 根據城市名稱查詢天氣 /cityName/{cityName}
WeatherDataService
/**
* @Author: cfx
* @Description: 天氣數據接口
* @Date: Created in 2018/4/5 10:38
*/
public interface WeatherDataService {
/**
* 根據城市Id查詢天氣
* @param cityId
* @return
*/
WeatherResponse getDataByCityId(String cityId);
/**
* 根據城市名稱查詢天氣
* @param cityName
* @return
*/
WeatherResponse getDataByCityName(String cityName);
}
WeatherDataServiceImpl
@Service
public class WeatherDataServiceImpl implements WeatherDataService {
private static final String WEATHER_URI = "http://wthrcdn.etouch.cn/weather_mini?";
@Autowired
private RestTemplate restTemplate;
@Override
public WeatherResponse getDataByCityId(String cityId) {
String uri = WEATHER_URI + "citykey=" + cityId;
return this.doGetWeather(uri);
}
@Override
public WeatherResponse getDataByCityName(String cityName) {
String uri = WEATHER_URI + "city=" + cityName;
return this.doGetWeather(uri);
}
/**
* 重構代碼
* @param uri
* @return
*/
private WeatherResponse doGetWeather(String uri) {
ResponseEntity<String> respString = restTemplate.getForEntity(uri,String.class);
//將接口返回的Json字符串轉換成對象
ObjectMapper mapper = new ObjectMapper();
WeatherResponse resp = null;
String strBody = null;
if (respString.getStatusCodeValue() == 200) {
strBody = respString.getBody();
}
try {
resp = mapper.readValue(strBody,WeatherResponse.class);
} catch (IOException e) {
e.printStackTrace();
}
return resp;
}
}
視圖控制層
WeatherController
@RestController
@RequestMapping("/weather")
public class WeatherController {
@Autowired
private WeatherDataService weatherDataService;
@GetMapping("/cityId/{cityId}")
public WeatherResponse getWeatherByCityId(@PathVariable("cityId") String cityId) {
return weatherDataService.getDataByCityId(cityId);
}
@GetMapping("/cityName/{cityName}")
public WeatherResponse getWeatherByCityName(@PathVariable("cityName") String cityName) {
return weatherDataService.getDataByCityName(cityName);
}
}
RestTemplate模板配置
@Configuration
public class RestConfiguration {
//啓動的時候要注意,由於我們在controller中注入了RestTemplate,所以啓動的時候需要實例化該類的一個實例
@Autowired
private RestTemplateBuilder builder;
@Bean
public RestTemplate restTemplate() {
return builder.build();
}
}
運行
輸入http://localhost:8080/weather/cityId/101280601
運行。
至此,基於SpringBoot的單體結構的天氣預報系統大體就完成了,後面還會基於此加入Redis和Quartz來提高系統性能。