获取第三方API天气数据
天气数据定时写库
@TOC
前言
基于想法来设计一个获取各个地方天气的相关信息,包括天气状况,湿度,温度,并且通过定时任务的方式写入到数据库。
一、步骤
1.获取天气数据的( climate天气,temp温度等)相关信息;
2.将获取的数据保存入对应的数据库表
二、方案计划
1.获取天气这块调用第三方的接口。
存入数据库这块通过接口来获取天气的实时数据。将数据库数据存入数据库表之中,由于天气是实时变化的,不同第三方的天气刷新时间次数不同,我们也跟着实时变化的话,服务器和资金消耗会增加,因此对于接口调用过来的参数通过定时任务来进行定时一小时重新请求,并且新增到数据库之中,且需要备份一条第三方接口来实现主接口失效的预备方案。
2.通过爬虫获取网站的相关天气数据
爬虫属于非法请求 请求次数多了 对方直接就风控了可能会造成(封IP 封帐号 返回假数据等)
三、第三方天气接口
以高德天气为例(个人认证天气API接口调用日上线30000次/日,并发量上限200次/秒,企业认证会增加,返回参数暂无光照度参数)
天气查询:天气查询API服务地址:restapi.amap.com/v3/weather/…
建议参照官方天气API说明(完整的参数文档):lbs.amap.com/api/webserv… 其他天气数据网站均可参照 1.高德地图(高德地图开发者平台):支持获取实时天气数据。 2.百度地图(百度地图开放平台):支持获取实时天气、天气预报还有指数,未来几天的天气等。 3.心知天气:支持获取国内369个地级市的天气实况、3天天气预报、生活指数等。 4.和风天气:支持获取国内3240多个城市以及海外4000多个城市的天气预报、实况天气、生活指数等。
1.用参存储
第一次用户传入的参数保存在redis中,之后每次获取参数都从redis中自动获取,用户重发请求覆盖原有redis的数据设计,此外可以通过存session中,默认保存时间有限只有15-30分钟,可以设计对应的参数数据表,将数据存入到数据库中等方案。
代码如下(示例):
@PostMapping("/{db}/{table}/XXX")
public JsonResult insertBySelectiveBaseStation(
@PathVariable String db, @PathVariable String table,
int xxx,String xxx,String memo,int city, String extensions, String output) {
int i = JudgeEntrance(db, table);
if (i == 1) {
stationClimateService.insertBySelectiveBaseStation(station,mode,memo,city, extensions, output);
}else {
throw new ServiceException(ServiceCode.ERR_CONFLICT, "路径库和表不对");
}
//第一次数据保存成功,将参数列表包装到DTO中存入redis中,之后自动更新参数从redis中取
StationWeatherDTO stationWeatherDTO= new StationWeatherDTO();
WeatherDTO.setMode(mode);
WeatherDTO.setStation(station);
WeatherDTO.setMemo(memo);
WeatherDTO.setCity(city);
WeatherDTO.setExtensions(extensions);
WeatherDTO.setOutput(output);
redisTemplate.boundValueOps(WeatherCacheCode.STATION_WEATHER_PARAM).set(stationWeatherDTO);
log.info("Station控制层入口redis数据缓存第一次传递的插入数据的值为{}",redisTemplate.boundValueOps(WeatherCacheCode.STATION_WEATHER_PARAM).get().toString());
return JsonResult.ok("站点天气数据添加成功");
}
2.InitializingBean接口为bean提供了初始化方法
它只包括afterPropertiesSet方法。凡是继承该接口的类,在初始化bean的时候会执行该方法。这种机制可以确保在bean的属性设置完成后调用初始化方法,保证bean的初始化过程正确执行。在Spring框架中,可以通过实现InitializingBean接口来定制bean的初始化过程,这样可以确保bean在容器启动时已经被正确地初始化。
代码如下(示例):
@Override
public void afterPropertiesSet() {
StringBuilder urlSb = new StringBuilder();
urlSb.append("https://restapi.amap.com/v3/weather/weatherInfo?");
urlSb.append("key=").append(weatherProp.getGdkey());
this.url = urlSb.toString();
StringBuilder urlHf = new StringBuilder();
urlHf.append("https://devapi.qweather.com/v7/weather/now?");
this.urlHfString = urlHf.toString();
}
该处使用的url网络请求的数据。
3.数据格式转换
代码如下(示例):
public WeatherVO getWeatherVO(int city,String extensions,String output) {
log.info("param city : {}", city);
log.info("param extensions : {}", extensions);
log.info("param output : {}", output);
String requrl = url +"&city=" + city + "&extensions=" + extensions + "&output=" + output;
log.info("高德接口第三方的传递URL:{}",requrl);
//restTemplate调用接口返回Json字符串数据
String responseStr = restTemplate.getForObject(requrl, String.class);
log.info("第三方传递回来的字符串数据:{}",responseStr);
WeatherVO weatherVO = JSON.parseObject(responseStr, WeatherVO.class);
return weatherVO;
}
4.Quartz任务调度
代码如下(示例):
@Component
public class StationWeatherJob implements Job {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private StationClimateService stationClimateService;
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//获取存在redis中的第一次station站点天气插入的参数数据
StationWeatherDTO stationWeatherDTO = (StationWeatherDTO) redisTemplate.boundValueOps(WeatherCacheCode.STATION_WEATHER_PARAM).get();
log.info("JOB类中redis中取出来的站点weatherDTO的数据:station:{},memo:{},city:{},extensions:{},output:{}", stationWeatherDTO.getStation(), stationWeatherDTO.getMemo(), stationWeatherDTO.getCity(), stationWeatherDTO.getExtensions(), stationWeatherDTO.getOutput());
//调Service,定时存入数据库
stationClimateService.insertBySelectiveBaseStation(stationWeatherDTO.getStation(), stationWeatherDTO.getMode(), stationWeatherDTO.getMemo(), stationWeatherDTO.getCity(), stationWeatherDTO.getExtensions(), stationWeatherDTO.getOutput());
}
}
3.业务处理
代码如下(示例):
@Override
public void insertBySelective(int agent,String mode,String memo,int city,String extensions,String output) {
//调用高德接口
WeatherVO weatherVO = weatherHandler.getWeatherVO(city, extensions, output);
log.info("打印的客户天气对象字符串" + weatherVO.toString());
log.info("WeatherVO对象的lives集合数据" + weatherVO.getLives());
//创建实体类,属性赋值
AgentClimate agentClimate = new AgentClimate();
//用来测试和风
// weatherVO = null;
if (weatherVO != null) {
for (LivesVO live : weatherVO.getLives()) {
agentClimate.setClimate(live.getWeather());
log.info("客户的高德当前天气{}", agentClimate.getClimate());
agentClimate.setTemp((double) live.getTemperature());
log.info("客户的高德当前为温度{}", agentClimate.getTemp());
}
}else if (weatherVO == null ){
//通过所在地获取HF返回地址
HfWeatherVO hfWeatherVO = weatherHandler.getHfWeatherVO(city);
for (NowVO nowVO : hfWeatherVO.getNow()) {
agentClimate.setClimate(nowVO.getText());
agentClimate.setTemp((double) nowVO.getTemp());
log.info("客户的和风当前天气{}", nowVO.getText());
log.info("客户的和风当前为温度{}", nowVO.getTemp());
}
} else {throw new ServiceException(ServiceCode.ERR_CONFLICT, "请稍后再试");}
agentClimate.setUpdateTime(LocalDateTime.now());
agentClimate.setAgent(agent);
agentClimate.setMode(mode);
//根据mode赋值
Long basedDt = basedOnMode(mode);
agentClimate.setDt(basedDt);
// agentClimate.setDt(Long.valueOf("11"));
agentClimate.setIrradiance(00.0);
agentClimate.setTime(LocalDateTime.now());
agentClimate.setCreatedTime(LocalDateTime.now());
agentClimate.setMemo(memo);
int i = agentClimateMapper.insertBySelective(agentClimate);
}
}
总结
1.数据格式类型转换问题,java解压缩Gzip文件使用IO流的方式; 2.用户数据自动调用所需参数使用redis,任务调度使用Quartz; 3.备份第三方接口问题,主线出现问题,支线自动替换;
转载自:https://juejin.cn/post/7251101434024067128