这是学习的第三篇文章,由于天气信息需要更新,所以我们需要一个定时器定时去获取一下最新的信息。由于本项目实现比较简单就可以用quartz来实现。
quartz如何整合
数据需要定时地刷新,不能等到用户来获取的时候才更新,这里用最常用的quartz定时器来实现。
首先时引入依赖:
1 2 3 4 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency>
下面定义一个执行的任务,先什么都不干,就打印一句话即可:
1 2 3 4 5 6 7 8 @Slf 4jpublic class WeatherDataSyncJob extends QuartzJobBean { @Override protected void executeInternal (JobExecutionContext context) throws JobExecutionException { log.info("天气数据同步任务开始" ); } }
下面要定义配置类:
首先是要定义这个任务的细节:JobDetail
,就是说我们配置的这个quartz里面的任务是谁?给他起个名字啥的。
后面个是定义触发器,决定了刚才定义的这个JobDetail
多长时间执行一次。这里是为了模拟想过,定义了两秒就执行一次。那么我们启动项目后,看到的效果应该是每两秒打印一次日志。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 @Configuration public class QuartzConfig { @Bean public JobDetail weatherDataSyncDetail () { return JobBuilder.newJob(WeatherDataSyncJob.class). withIdentity("WeatherDataSyncJob" ). storeDurably().build(); } @Bean public Trigger weatherDataSyncTrigger () { SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder .simpleSchedule() .withIntervalInSeconds(2 ) .repeatForever(); return TriggerBuilder.newTrigger().forJob(weatherDataSyncDetail()) .withIdentity("weatherDataSyncTrigger" ) .withSchedule(scheduleBuilder).build(); } }
拉取城市信息
网站: http://mobile.weather.com.cn/js/citylist.xml
比如我将江苏省的单独拿出来:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 <xml > <c c1 ="0" > <d d1 ="101190101" d2 ="南京" d3 ="nanjing" d4 ="江苏" /> <d d1 ="101190102" d2 ="溧水" d3 ="lishui" d4 ="江苏" /> <d d1 ="101190103" d2 ="高淳" d3 ="gaochun" d4 ="江苏" /> <d d1 ="101190104" d2 ="江宁" d3 ="jiangning" d4 ="江苏" /> <d d1 ="101190105" d2 ="六合" d3 ="luhe" d4 ="江苏" /> <d d1 ="101190106" d2 ="江浦" d3 ="jiangpu" d4 ="江苏" /> <d d1 ="101190107" d2 ="浦口" d3 ="pukou" d4 ="江苏" /> <d d1 ="101190201" d2 ="无锡" d3 ="wuxi" d4 ="江苏" /> <d d1 ="101190202" d2 ="江阴" d3 ="jiangyin" d4 ="江苏" /> <d d1 ="101190203" d2 ="宜兴" d3 ="yixing" d4 ="江苏" /> <d d1 ="101190204" d2 ="锡山" d3 ="xishan" d4 ="江苏" /> <d d1 ="101190301" d2 ="镇江" d3 ="zhenjiang" d4 ="江苏" /> <d d1 ="101190302" d2 ="丹阳" d3 ="danyang" d4 ="江苏" /> <d d1 ="101190303" d2 ="扬中" d3 ="yangzhong" d4 ="江苏" /> <d d1 ="101190304" d2 ="句容" d3 ="jurong" d4 ="江苏" /> <d d1 ="101190305" d2 ="丹徒" d3 ="dantu" d4 ="江苏" /> <d d1 ="101190401" d2 ="苏州" d3 ="suzhou" d4 ="江苏" /> <d d1 ="101190402" d2 ="常熟" d3 ="changshu" d4 ="江苏" /> <d d1 ="101190403" d2 ="张家港" d3 ="zhangjiagang" d4 ="江苏" /> <d d1 ="101190404" d2 ="昆山" d3 ="kunshan" d4 ="江苏" /> <d d1 ="101190405" d2 ="吴中" d3 ="wuzhong" d4 ="江苏" /> <d d1 ="101190407" d2 ="吴江" d3 ="wujiang" d4 ="江苏" /> <d d1 ="101190408" d2 ="太仓" d3 ="taicang" d4 ="江苏" /> <d d1 ="101190501" d2 ="南通" d3 ="nantong" d4 ="江苏" /> <d d1 ="101190502" d2 ="海安" d3 ="haian" d4 ="江苏" /> <d d1 ="101190503" d2 ="如皋" d3 ="rugao" d4 ="江苏" /> <d d1 ="101190504" d2 ="如东" d3 ="rudong" d4 ="江苏" /> <d d1 ="101190507" d2 ="启东" d3 ="qidong" d4 ="江苏" /> <d d1 ="101190508" d2 ="海门" d3 ="haimen" d4 ="江苏" /> <d d1 ="101190509" d2 ="通州" d3 ="tongzhou" d4 ="江苏" /> <d d1 ="101190601" d2 ="扬州" d3 ="yangzhou" d4 ="江苏" /> <d d1 ="101190602" d2 ="宝应" d3 ="baoying" d4 ="江苏" /> <d d1 ="101190603" d2 ="仪征" d3 ="yizheng" d4 ="江苏" /> <d d1 ="101190604" d2 ="高邮" d3 ="gaoyou" d4 ="江苏" /> <d d1 ="101190605" d2 ="江都" d3 ="jiangdu" d4 ="江苏" /> <d d1 ="101190606" d2 ="邗江" d3 ="hanjiang" d4 ="江苏" /> <d d1 ="101190701" d2 ="盐城" d3 ="yancheng" d4 ="江苏" /> <d d1 ="101190702" d2 ="响水" d3 ="xiangshui" d4 ="江苏" /> <d d1 ="101190703" d2 ="滨海" d3 ="binhai" d4 ="江苏" /> <d d1 ="101190704" d2 ="阜宁" d3 ="funing" d4 ="江苏" /> <d d1 ="101190705" d2 ="射阳" d3 ="sheyang" d4 ="江苏" /> <d d1 ="101190706" d2 ="建湖" d3 ="jianhu" d4 ="江苏" /> <d d1 ="101190707" d2 ="东台" d3 ="dongtai" d4 ="江苏" /> <d d1 ="101190708" d2 ="大丰" d3 ="dafeng" d4 ="江苏" /> <d d1 ="101190709" d2 ="盐都" d3 ="yandu" d4 ="江苏" /> <d d1 ="101190801" d2 ="徐州" d3 ="xuzhou" d4 ="江苏" /> <d d1 ="101190802" d2 ="铜山" d3 ="tongshan" d4 ="江苏" /> <d d1 ="101190803" d2 ="丰县" d3 ="fengxian" d4 ="江苏" /> <d d1 ="101190804" d2 ="沛县" d3 ="peixian" d4 ="江苏" /> <d d1 ="101190805" d2 ="邳州" d3 ="pizhou" d4 ="江苏" /> <d d1 ="101190806" d2 ="睢宁" d3 ="suining" d4 ="江苏" /> <d d1 ="101190807" d2 ="新沂" d3 ="xinyi" d4 ="江苏" /> <d d1 ="101190901" d2 ="淮安" d3 ="huaian" d4 ="江苏" /> <d d1 ="101190902" d2 ="金湖" d3 ="jinhu" d4 ="江苏" /> <d d1 ="101190903" d2 ="盱眙" d3 ="xuyi" d4 ="江苏" /> <d d1 ="101190904" d2 ="洪泽" d3 ="hongze" d4 ="江苏" /> <d d1 ="101190905" d2 ="涟水" d3 ="lianshui" d4 ="江苏" /> <d d1 ="101190906" d2 ="淮阴区" d3 ="huaiyinqu" d4 ="江苏" /> <d d1 ="101190908" d2 ="淮安区" d3 ="huaianqu" d4 ="江苏" /> <d d1 ="101191001" d2 ="连云港" d3 ="lianyungang" d4 ="江苏" /> <d d1 ="101191002" d2 ="东海" d3 ="donghai" d4 ="江苏" /> <d d1 ="101191003" d2 ="赣榆" d3 ="ganyu" d4 ="江苏" /> <d d1 ="101191004" d2 ="灌云" d3 ="guanyun" d4 ="江苏" /> <d d1 ="101191005" d2 ="灌南" d3 ="guannan" d4 ="江苏" /> <d d1 ="101191101" d2 ="常州" d3 ="changzhou" d4 ="江苏" /> <d d1 ="101191102" d2 ="溧阳" d3 ="liyang" d4 ="江苏" /> <d d1 ="101191103" d2 ="金坛" d3 ="jintan" d4 ="江苏" /> <d d1 ="101191104" d2 ="武进" d3 ="wujin" d4 ="江苏" /> <d d1 ="101191201" d2 ="泰州" d3 ="taizhou" d4 ="江苏" /> <d d1 ="101191202" d2 ="兴化" d3 ="xinghua" d4 ="江苏" /> <d d1 ="101191203" d2 ="泰兴" d3 ="taixing" d4 ="江苏" /> <d d1 ="101191204" d2 ="姜堰" d3 ="jiangyan" d4 ="江苏" /> <d d1 ="101191205" d2 ="靖江" d3 ="jingjiang" d4 ="江苏" /> <d d1 ="101191301" d2 ="宿迁" d3 ="suqian" d4 ="江苏" /> <d d1 ="101191302" d2 ="沭阳" d3 ="shuyang" d4 ="江苏" /> <d d1 ="101191303" d2 ="泗阳" d3 ="siyang" d4 ="江苏" /> <d d1 ="101191304" d2 ="泗洪" d3 ="sihong" d4 ="江苏" /> <d d1 ="101191305" d2 ="宿豫" d3 ="suyu" d4 ="江苏" /> </c > </xml >
其实思路很简单,就是从xml文件中获取所有的城市信息,转换为城市列表对象。然后遍历城市中的id,就可以根据id拼接url去直接去调用天气的接口去查询天气,然后重新覆盖redis中的天气数据即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 @Slf 4jpublic class WeatherDataSyncJob extends QuartzJobBean { @Autowired private IWeatherDataService weatherDataService; @Autowired private ICityDataService cityDataService; @Override protected void executeInternal (JobExecutionContext context) throws JobExecutionException { log.info("天气数据同步任务开始" ); List<City> cityList = null ; try { cityList = cityDataService.listCity(); } catch (Exception e) { log.error("获取城市列表失败!" ,e); } for (City city:cityList){ String cityId = city.getCityId(); log.info("定时器更新了{}这个城市的天气信息" , city.getCityName()); weatherDataService.syncDataByCityId(cityId); } log.info("天气数据同步任务结束" ); } }
具体如何读取xml文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 @Service @Slf 4jpublic class CityDataServiceImpl implements ICityDataService { @Override public List<City> listCity () throws Exception { Resource resource = new ClassPathResource("citylist.xml" ); BufferedReader bf = new BufferedReader(new InputStreamReader(resource.getInputStream(),"UTF-8" )); StringBuffer buffer = new StringBuffer(); String line = "" ; while ((line = bf.readLine()) != null ){ buffer.append(line); } bf.close(); CityList cityList = (CityList) XmlBuilder.xmlStrToObj(CityList.class,buffer.toString()); return cityList.getCityList(); } } public class XmlBuilder { public static Object xmlStrToObj (Class<?> clazz,String xmlStr) throws Exception { Object xmlObject = null ; Reader reader = null ; JAXBContext context = JAXBContext.newInstance(clazz); Unmarshaller unmarshaller = context.createUnmarshaller(); reader = new StringReader(xmlStr); xmlObject = unmarshaller.unmarshal(reader); if (null != reader){ reader.close(); } return xmlObject; } }
其中,解析xml我们用到了JAXB
,他是什么呢?维基百科:
JAXB(Java Architecture for XML Binding简称JAXB)允许Java开发人员将Java类映射为XML表示方式。JAXB提供两种主要特性:将一个Java对象序列化为XML,以及反向操作,将XML解析成Java对象。换句话说,JAXB允许以XML格式存储和读取数据,而不需要程序的类结构实现特定的读取XML和保存XML的代码。