SpringCloud学习之旅05--weather项目集成quartz(定时器)和Redis

目录结构:

SpringCloud学习之旅05--weather项目集成quartz(定时器)和Redis_第1张图片

build.gradle文件:

// buildscript 代码块中脚本优先执行
buildscript {


// ext 用于定义动态属性
ext {
springBootVersion = '2.0.0.M4'
}


// 使用了Maven的中央仓库及Spring自己的仓库(也可以指定其他仓库)
repositories {
// mavenCentral()
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }
maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
}


// 依赖关系
dependencies {


// classpath 声明了在执行其余的脚本时,ClassLoader 可以使用这些依赖项
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}


// 使用插件
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

// 指定了生成的编译文件的版本,默认是打成了 jar 包

group = 'com.waylau.spring.cloud'
version = '1.0.0'


// 指定编译 .java 文件的 JDK 版本
sourceCompatibility = 1.8

// 使用了Maven的中央仓库及Spring自己的仓库(也可以指定其他仓库)
repositories {
//mavenCentral()
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }
maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
}


// 依赖关系
dependencies {

        // 该依赖用于编译阶段
compile('org.springframework.boot:spring-boot-starter-web')


// HttpClient
compile('org.apache.httpcomponents:httpclient:4.5.3')


// Redis
compile('org.springframework.boot:spring-boot-starter-data-redis')


// Quartz
compile('org.springframework.boot:spring-boot-starter-quartz')


testCompile('org.springframework.boot:spring-boot-starter-test')

}

 

citylist.xml文件:(这里没有存储数据库,因为这些是一些常量值,不长变化的,所以可以保存为xml文件)



















































































































 

实体类:VO

package com.waylau.spring.cloud.weather.vo;


import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;


/**
 * City.
 * 
 * @since 1.0.0 2017年11月23日
 * @author Way Lau 
 */
@XmlRootElement(name = "d")
@XmlAccessorType(XmlAccessType.FIELD)
public class City {
@XmlAttribute(name = "d1")
private String cityId;

@XmlAttribute(name = "d2")
private String cityName;

@XmlAttribute(name = "d3")
private String cityCode;

@XmlAttribute(name = "d4")
private String province;


public String getCityId() {
return cityId;
}


public void setCityId(String cityId) {
this.cityId = cityId;
}


public String getCityName() {
return cityName;
}


public void setCityName(String cityName) {
this.cityName = cityName;
}


public String getCityCode() {
return cityCode;
}


public void setCityCode(String cityCode) {
this.cityCode = cityCode;
}


public String getProvince() {
return province;
}


public void setProvince(String province) {
this.province = province;
}

}

 

package com.waylau.spring.cloud.weather.vo;


import java.util.List;


import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;


/**
 * City List.
 * 
 * @since 1.0.0 2017年11月23日
 * @author Way Lau 
 */
@XmlRootElement(name = "c")
@XmlAccessorType(XmlAccessType.FIELD)
public class CityList {
@XmlElement(name = "d")
private List cityList;


public List getCityList() {
return cityList;
}


public void setCityList(List cityList) {
this.cityList = cityList;
}

}



 

package com.waylau.spring.cloud.weather.vo;


import java.io.Serializable;


/**
 * 未来天气.
 * 
 * @since 1.0.0 2017年11月21日
 * @author Way Lau 
 */
public class Forecast implements Serializable {


private static final long serialVersionUID = 1L;
private String date;
private String high;
private String fengli;
private String low;
private String fengxiang;
private String type;
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getHigh() {
return high;
}
public void setHigh(String high) {
this.high = high;
}
public String getFengli() {
return fengli;
}
public void setFengli(String fengli) {
this.fengli = fengli;
}
public String getLow() {
return low;
}
public void setLow(String low) {
this.low = low;
}
public String getFengxiang() {
return fengxiang;
}
public void setFengxiang(String fengxiang) {
this.fengxiang = fengxiang;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}



}
package com.waylau.spring.cloud.weather.vo;


import java.io.Serializable;
import java.util.List;


/**
 * 天气信息.
 * 
 * @since 1.0.0 2017年11月21日
 * @author Way Lau 
 */
public class Weather implements Serializable {


private static final long serialVersionUID = 1L;

private String city;
private String aqi;
private String ganmao;
private String wendu;
private Yeaterday yesterday;
private List forecast;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getAqi() {
return aqi;
}
public void setAqi(String aqi) {
this.aqi = aqi;
}
public String getGanmao() {
return ganmao;
}
public void setGanmao(String ganmao) {
this.ganmao = ganmao;
}
public String getWendu() {
return wendu;
}
public void setWendu(String wendu) {
this.wendu = wendu;
}
public Yeaterday getYesterday() {
return yesterday;
}
public void setYesterday(Yeaterday yesterday) {
this.yesterday = yesterday;
}
public List getForecast() {
return forecast;
}
public void setForecast(List forecast) {
this.forecast = forecast;
}



}

 

package com.waylau.spring.cloud.weather.vo;


import java.io.Serializable;


/**
 * Weather Response.
 * 
 * @since 1.0.0 2017年11月21日
 * @author Way Lau 
 */
public class WeatherResponse implements Serializable {


private static final long serialVersionUID = 1L;
private Weather data;
private Integer status;
private String desc;
public Weather getData() {
return data;
}
public void setData(Weather data) {
this.data = data;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}


}

 

package com.waylau.spring.cloud.weather.vo;


import java.io.Serializable;


/**
 * 昨日天气.
 * 
 * @since 1.0.0 2017年11月21日
 * @author Way Lau 
 */
public class Yeaterday implements Serializable {
private static final long serialVersionUID = 1L;
private String date;
private String high;
private String fx;
private String low;
private String fl;
private String type;
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getHigh() {
return high;
}
public void setHigh(String high) {
this.high = high;
}
public String getFx() {
return fx;
}
public void setFx(String fx) {
this.fx = fx;
}
public String getLow() {
return low;
}
public void setLow(String low) {
this.low = low;
}
public String getFl() {
return fl;
}
public void setFl(String fl) {
this.fl = fl;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}

}

 

XmlBuilder工具类将xml转为object对象:

package com.waylau.spring.cloud.weather.util;


import java.io.Reader;
import java.io.StringReader;


import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;


/**
 * Xml Builder.
 * 
 * @since 1.0.0 2017年11月23日
 * @author Way Lau 
 */
public class XmlBuilder {


/**
* 将XML转为指定的POJO
* @param clazz
* @param xmlStr
* @return
* @throws Exception
*/
public static Object xmlStrToOject(Class clazz, String xmlStr) throws Exception {
Object xmlObject = null;
Reader reader = null;
JAXBContext context = JAXBContext.newInstance(clazz);

// XML 转为对象的接口
Unmarshaller unmarshaller = context.createUnmarshaller();

reader = new StringReader(xmlStr);
xmlObject = unmarshaller.unmarshal(reader);

if (null != reader) {
reader.close();
}

return xmlObject;
}

}

 

service:

package com.waylau.spring.cloud.weather.service;


import java.util.List;


import com.waylau.spring.cloud.weather.vo.City;


/**
 * City Data Service.
 * 
 * @since 1.0.0 2017年11月23日
 * @author Way Lau 
 */
public interface CityDataService {


/**
* 获取City列表
* @return
* @throws Exception
*/
List listCity() throws Exception;

}

 

package com.waylau.spring.cloud.weather.service;


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.List;


import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;


import com.waylau.spring.cloud.weather.util.XmlBuilder;
import com.waylau.spring.cloud.weather.vo.City;
import com.waylau.spring.cloud.weather.vo.CityList;


/**
 * City Data Service.
 * 
 * @since 1.0.0 2017年11月23日
 * @author Way Lau 
 */
@Service
public class CityDataServiceImpl implements CityDataService {


@Override
public List listCity() throws Exception {
// 读取XML文件
Resource resource = new ClassPathResource("citylist.xml");
BufferedReader br = new BufferedReader(new InputStreamReader(resource.getInputStream(), "utf-8"));
StringBuffer buffer = new StringBuffer();
String line = "";

while ((line = br.readLine()) !=null) {
buffer.append(line);
}

br.close();

// XML转为Java对象
CityList cityList = (CityList)XmlBuilder.xmlStrToOject(CityList.class, buffer.toString());
return cityList.getCityList();
}



}

 

package com.waylau.spring.cloud.weather.service;


import com.waylau.spring.cloud.weather.vo.WeatherResponse;


/**
 * Weather Data Service.
 * 
 * @since 1.0.0 2017年11月22日
 * @author Way Lau 
 */
public interface WeatherDataService {
/**
* 根据城市ID查询天气数据
* 
* @param cityId
* @return
*/
WeatherResponse getDataByCityId(String cityId);


/**
* 根据城市名称查询天气数据
* 
* @param cityId
* @return
*/
WeatherResponse getDataByCityName(String cityName);

/**
* 根据城市ID来同步天气
* @param cityId
*/
void syncDateByCityId(String cityId);


}

 

package com.waylau.spring.cloud.weather.service;


import java.io.IOException;
import java.util.concurrent.TimeUnit;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.waylau.spring.cloud.weather.vo.WeatherResponse;


/**
 * WeatherDataService 实现.
 * 
 * @since 1.0.0 2017年11月22日
 * @author Way Lau 
 */
@Service
public class WeatherDataServiceImpl implements WeatherDataService {
private final static Logger logger = LoggerFactory.getLogger(WeatherDataServiceImpl.class);  

private static final String WEATHER_URI = "http://wthrcdn.etouch.cn/weather_mini?";


private static final long TIME_OUT = 1800L; // 1800s

@Autowired
private RestTemplate restTemplate;

@Autowired
private StringRedisTemplate stringRedisTemplate;

@Override
public WeatherResponse getDataByCityId(String cityId) {
String uri = WEATHER_URI + "citykey=" + cityId;
return this.doGetWeahter(uri);
}


@Override
public WeatherResponse getDataByCityName(String cityName) {
String uri = WEATHER_URI + "city=" + cityName;
return this.doGetWeahter(uri);
}

private WeatherResponse doGetWeahter(String uri) {
String key = uri;
String strBody = null;
ObjectMapper mapper = new ObjectMapper();
WeatherResponse resp = null;
ValueOperations  ops = stringRedisTemplate.opsForValue();
// 先查缓存,缓存有的取缓存中的数据
if (stringRedisTemplate.hasKey(key)) {
logger.info("Redis has data");
strBody = ops.get(key);
} else {
logger.info("Redis don't has data");
// 缓存没有,再调用服务接口来获取
ResponseEntity respString = restTemplate.getForEntity(uri, String.class);


if (respString.getStatusCodeValue() == 200) {
strBody = respString.getBody();
}

// 数据写入缓存
ops.set(key, strBody, TIME_OUT, TimeUnit.SECONDS);
}


try {
resp = mapper.readValue(strBody, WeatherResponse.class);
} catch (IOException e) {
//e.printStackTrace();
logger.error("Error!",e);
}

return resp;
}


@Override
public void syncDateByCityId(String cityId) {
String uri = WEATHER_URI + "citykey=" + cityId;
this.saveWeatherData(uri);
}

/**
* 把天气数据放在缓存
* @param uri
*/
private void saveWeatherData(String uri) {
String key = uri;
String strBody = null;
ValueOperations  ops = stringRedisTemplate.opsForValue();


// 调用服务接口来获取
  ResponseEntity respString = restTemplate.getForEntity(uri, String.class);


  if (respString.getStatusCodeValue() == 200) {
strBody = respString.getBody();
}

// 数据写入缓存
ops.set(key, strBody, TIME_OUT, TimeUnit.SECONDS);


}



}

 

config配置类:

package com.waylau.spring.cloud.weather.config;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;


/**
 * Rest Configuration.
 * 
 * @since 1.0.0 2017年11月22日
 * @author Way Lau 
 */
@Configuration
public class RestConfiguration {

@Autowired
private RestTemplateBuilder builder;


@Bean
public RestTemplate restTemplate() {
return builder.build();
}


}

 

package com.waylau.spring.cloud.weather.config;


import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


import com.waylau.spring.cloud.weather.job.WeatherDataSyncJob;


/**
 * Quartz Configuration.
 * 
 * @since 1.0.0 2017年11月23日
 * @author Way Lau 
 */
@Configuration
public class QuartzConfiguration {


private static final int TIME = 1800; // 更新频率


// JobDetail  指定特定的job
@Bean
public JobDetail weatherDataSyncJobDetail() {
return JobBuilder.newJob(WeatherDataSyncJob.class).withIdentity("weatherDataSyncJob")
.storeDurably().build();
}

// Trigger  job触发
@Bean
public Trigger weatherDataSyncTrigger() {

SimpleScheduleBuilder schedBuilder = SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(TIME).repeatForever();

return TriggerBuilder.newTrigger().forJob(weatherDataSyncJobDetail())
.withIdentity("weatherDataSyncTrigger").withSchedule(schedBuilder).build();
}

}

 

package com.waylau.spring.cloud.weather.job;


import java.util.List;


import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;


import com.waylau.spring.cloud.weather.service.CityDataService;
import com.waylau.spring.cloud.weather.service.WeatherDataService;
import com.waylau.spring.cloud.weather.vo.City;


/**
 * Weather Data Sync Job.
 * 
 * @since 1.0.0 2017年11月23日
 * @author Way Lau 
 */
public class WeatherDataSyncJob extends QuartzJobBean {

private final static Logger logger = LoggerFactory.getLogger(WeatherDataSyncJob.class);  

@Autowired
private CityDataService cityDataService;

@Autowired
private WeatherDataService weatherDataService;
/* (non-Javadoc)
* @see org.springframework.scheduling.quartz.QuartzJobBean#executeInternal(org.quartz.JobExecutionContext)
*/
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
logger.info("Weather Data Sync Job. Start!");
// 获取城市ID列表
List cityList = null;

try {
cityList = cityDataService.listCity();
} catch (Exception e) {
logger.error("Exception!", e);
}

// 遍历城市ID获取天气
for (City city : cityList) {
String cityId = city.getCityId();
logger.info("Weather Data Sync Job, cityId:" + cityId);

weatherDataService.syncDateByCityId(cityId);
}

logger.info("Weather Data Sync Job. End!");
}



}



 

WeatherController控制器:

package com.waylau.spring.cloud.weather.controller;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


import com.waylau.spring.cloud.weather.service.WeatherDataService;
import com.waylau.spring.cloud.weather.vo.WeatherResponse;
/**
 * Weather Controller.
 * 
 * @since 1.0.0 2017年11月22日
 * @author Way Lau 
 */
@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);
}

}



 

最后访问链接:

http://localhost:8080/weather/cityId/101042400

SpringCloud学习之旅05--weather项目集成quartz(定时器)和Redis_第2张图片

http://localhost:8080/weather/cityName/深圳

SpringCloud学习之旅05--weather项目集成quartz(定时器)和Redis_第3张图片

 

Redis存储结果:

SpringCloud学习之旅05--weather项目集成quartz(定时器)和Redis_第4张图片

SpringCloud学习之旅05--weather项目集成quartz(定时器)和Redis_第5张图片

你可能感兴趣的:(springcloud)