基于第三方SDK获取城市实时天气信息

770 阅读3分钟

这是我参与新手入门的第1篇文章

作为刚入职场的Java小菜鸟,接触到新鲜任务都是兴奋的(骗人的),今天领导给了一个新的需求,显示指定城市的实时天气。这不信手拈来吗,遍地的第三方,任君挑选~~

微信图片_20210401090421.jpg

直接开冲好吧!!!

一、选择合适的第三方

对于业务来说,没有最好的技术,只有最适合的技术,所以选择一个合适的第三方API就能走少很多弯路了。鉴于业务展示的数据并不需要太精细,就是个展示效果。加上领导们本着好钢要用在刀刃上的道理(老扣了),本次选择用的第三方是和风天气API

二、获取和风认证Key

登录平台后进入和风天气开发者控制台,选择 应用管理创建应用免费开发者版本 ;并输入自定义名称即可,获取到如图所示Key值。

1625478932(1).png

三、参数准备

本次调用的第三方API所需要的的参数为

  • 请求路径:devapi.qweather.com/v7/weather/…]
  • Key值(必选)用户认证key。例如 key=123456789ABC
  • location (必选)需要查询地区的LocationID或以英文逗号分隔的经度,纬度坐标(十进制)例如 location=101010100 或 location=116.41,39.92
  • gzip(可选)对API接口进行压缩,可以极大的减少API接口访问延迟,减少缓存空间,提高接口连接成功率。默认开启gzip(如果项目配置文件开启了gzip接口压缩,则默认需要)

由于项目需要(其实是偷懒),采用的是经纬度的方法;因为使用LocationId的话,后端(我)需要新建表存起来所有的LocationId和地区名称,前端小伙伴需要用树状下拉框供用户选择,加上项目前端有地图控件,所以选择使用经纬度,有需要的小伙伴也可以视项目情况为定,一切以业务优先。

四、调用接口

1、从内到外设计接口

graph TD
    接口调用--> C{查询缓存}
    C --> |缓存存在| D[输出]
    C --> |缓存不存在| E[发起网络请求并更新缓存+输出]

2、查询缓存

    public FarmWeatherDTO selectWeather(Long areaId) {
        Assert.notNull(areaId, "areaId not be null.");
        String str = SafeRedisHelper.execute(WfService.Platform.REDIS_DB,
                () -> redisHelper.strGet(DATABASE_KEY+areaId+""));
        FarmWeatherDTO farmWeatherDto = null;
        if (StringUtils.isNotBlank(str)) {
            farmWeatherDto = redisHelper.fromJson(str, FarmWeatherDTO.class);
            return farmWeatherDto;
        } else {
            return null;
        }
    }

3、发起网络请求

key值与url都写在配置文件内,用反射获取并调用该方法

    public static FarmWeatherDTO getWeather(String location, String key, String url){
        try {
        UriComponentsBuilder builder = UriComponentsBuilder
                .fromHttpUrl(url)
                .queryParam(LOCATION, location)
                .queryParam(KEY,key)
                .queryParam(GZIP,N);
        URI uri =  builder.build(true).toUri();
        RestTemplate restTemplate = new RestTemplate();
        //修改编码集
        HttpUtils.setRestTemplateEncode(restTemplate);
        //城市地标
            String result = restTemplate.getForObject(uri,String.class);
            JSONObject jsonObject = JSONObject.parseObject(result);
            if (jsonObject.getString(CODE).equals(SUCCESS)){
                FarmWeatherDTO farmWeatherDto = JSONObject.parseObject(jsonObject.getString(NOW), FarmWeatherDTO.class);
                System.out.println(farmWeatherDto);
                return farmWeatherDto;
            }else {
                throw new CommonException("wfpf.area.weatherError");
            }
        }catch (Exception e){
            throw new CommonException("wfpf.area.weatherError");
        }
    }

4、存储缓存

    public void saveWeather(Long areaId, FarmWeatherDTO weatherDto) {
        Assert.notNull(weatherDto, "weather not be null.");
        SafeRedisHelper.execute(STongService.Oauth.REDIS_DB, redisHelper,
                () -> redisHelper.strSet(DATABASE_KEY+areaId+"",redisHelper.toJson(weatherDto),MINUTE, TimeUnit.MINUTES));
    }

数据实现

{
    "code": "200",
    "updateTime": "2021-07-05T23:47+08:00",
    "fxLink": "http://hfx.link/3hb1",
    "now": {
        "obsTime": "2021-07-05T23:35+08:00",
        "temp": "29",
        "feelsLike": "32",
        "icon": "101",
        "text": "多云",
        "wind360": "135",
        "windDir": "东南风",
        "windScale": "2",
        "windSpeed": "9",
        "humidity": "73",
        "precip": "0.0",
        "pressure": "1000",
        "vis": "30",
        "cloud": "4",
        "dew": "26"
    },
    "refer": {
        "sources": [
            "Weather China"
        ],
        "license": [
            "no commercial use"
        ]
    }
}

页面展示

Image 1.png

总结

  1. 接口设计的话使用的优先取缓存,考虑到天气变化性以及持久性,1个小时或以上作为过期时间,减少频繁发起网络请求,加快接口响应速度;
  2. 这是第一次写文章轻点吐槽。(我怕自己坚持不住“脸皮薄”没办法)
  3. 本方法仅代表个人看法,广泛采纳各位看官意见,多多益善嘻嘻嘻~