前言

本系列文章将简单的学习SpringCloud微服务相关知识,其实也是因为时间的原因,一直拖到现在,遂打算趁着假期,决定记录下来。

从天气预报微服务系统的单体架构——>分布式架构的演变过程中,一步一步,由浅及深的学习SpringCloud微服务的思想与其实现的组件。

本系列文章分为以下几个章节:

项目源码已上传至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来提高系统性能。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐