这是我参与新手入门的第1篇文章
作为刚入职场的Java小菜鸟,接触到新鲜任务都是兴奋的(骗人的),今天领导给了一个新的需求,显示指定城市的实时天气。这不信手拈来吗,遍地的第三方,任君挑选~~
直接开冲好吧!!!
一、选择合适的第三方
对于业务来说,没有最好的技术,只有最适合的技术,所以选择一个合适的第三方API就能走少很多弯路了。鉴于业务展示的数据并不需要太精细,就是个展示效果。加上领导们本着好钢要用在刀刃上的道理(老扣了),本次选择用的第三方是和风天气API
二、获取和风认证Key
登录平台后进入和风天气开发者控制台,选择 应用管理 → 创建应用 → 免费开发者版本 ;并输入自定义名称即可,获取到如图所示Key值。
三、参数准备
本次调用的第三方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"
]
}
}
页面展示
总结
- 接口设计的话使用的优先取缓存,考虑到天气变化性以及持久性,1个小时或以上作为过期时间,减少频繁发起网络请求,加快接口响应速度;
- 这是第一次写文章轻点吐槽。(我怕自己坚持不住“脸皮薄”没办法)
- 本方法仅代表个人看法,广泛采纳各位看官意见,多多益善嘻嘻嘻~