1.天气数据采集微服务的实现
单体项目-------------------》msa-weather-collection-server
要利用redis,quartz
该微服务只需要做到对天气数据的同步 void syncDateByCityId(String cityId); 通过城市来采集和同步数据
之前单体的项目redis和quartz配置部分不变 只要添加WeatherDataCollectionService接口和其实现类
/**
* Weather Data Collection Service.
*
*/
public interface WeatherDataCollectionService {
/**
* 根据城市ID同步天气
* @param cityId
*/
void syncDateByCityId(String cityId);
}
import java.util.concurrent.TimeUnit;
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;
/**
* Weather Data Collection Service.
*
*/
@Service
public class WeatherDataCollectionServiceImpl implements WeatherDataCollectionService {
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 void syncDateByCityId(String cityId) {
String uri = WEATHER_URI + "citykey=" + cityId;
this.saveWeatherData(uri);
}
/**
* 直接通过城市id访问API把天气数据放在缓存
* @param uri
*/
private void saveWeatherData(String uri) {
String key = uri;
String strBody = null;
ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
// 调用服务接口来获取
ResponseEntity<String> respString = restTemplate.getForEntity(uri, String.class);
if (respString.getStatusCodeValue() == 200) {
strBody = respString.getBody();
}
// 数据写入缓存
ops.set(key, strBody, TIME_OUT, TimeUnit.SECONDS);
}
}
quartz执行的job也得改一下 不能直接调用城市数据
import java.util.ArrayList;
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.WeatherDataCollectionService;
import com.waylau.spring.cloud.weather.vo.City;
/**
* Weather Data Sync Job.
*
*/
public class WeatherDataSyncJob extends QuartzJobBean {
private final static Logger logger = LoggerFactory.getLogger(WeatherDataSyncJob.class);
@Autowired
private WeatherDataCollectionService weatherDataCollectionService;
/* (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列表
// TODO 改为由城市数据API微服务来提供数据
List<City> cityList = null;
try {
// TODO 改为由城市数据API微服务提供数据
cityList = new ArrayList<>();
City city = new City();
city.setCityId("101280601");
cityList.add(city);
} catch (Exception e) {
logger.error("Exception!", e);
}
// 遍历城市ID获取天气
for (City city : cityList) {
String cityId = city.getCityId();
logger.info("Weather Data Sync Job, cityId:" + cityId);
weatherDataCollectionService.syncDateByCityId(cityId);
}
logger.info("Weather Data Sync Job. End!");
}
}
2.天气预报微服务的实现 (展示给用户看 UI界面)
只设计天气数据的展示
单体项目-------------------》msa-weather-report-server
会调用WeatherDataServer 获取整个的返回格式 只取weather天气数据部分
利用前端thymeleaf和bootstrap
WeatherReportController
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
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 org.springframework.web.servlet.ModelAndView;
import com.waylau.spring.cloud.weather.service.WeatherReportService;
import com.waylau.spring.cloud.weather.vo.City;
/**
* Weather Report Controller.
*
*/
@RestController
@RequestMapping("/report")
public class WeatherReportController {
private final static Logger logger = LoggerFactory.getLogger(WeatherReportController.class);
@Autowired
private WeatherReportService weatherReportService;
@GetMapping("/cityId/{cityId}")
public ModelAndView getReportByCityId(@PathVariable("cityId") String cityId, Model model) throws Exception {
// 获取城市ID列表
// TODO 改为由城市数据API微服务来提供数据
List<City> cityList = null;
try {
// TODO 改为由城市数据API微服务提供数据
cityList = new ArrayList<>();
City city = new City();
city.setCityId("101280601");
city.setCityName("深圳");
cityList.add(city);
} catch (Exception e) {
logger.error("Exception!", e);
}
model.addAttribute("title", "天气预报");
model.addAttribute("cityId", cityId);
model.addAttribute("cityList", cityList);
model.addAttribute("report", weatherReportService.getDataByCityId(cityId));
return new ModelAndView("weather/report", "reportModel", model);
}
}
import com.waylau.spring.cloud.weather.vo.Weather;
/**
* Weather Report Service.
*
*/
public interface WeatherReportService {
/**
* 根据城市ID查询天气信息
* @param cityId
* @return
*/
Weather getDataByCityId(String cityId);
}
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import com.waylau.spring.cloud.weather.vo.Forecast;
import com.waylau.spring.cloud.weather.vo.Weather;
/**
* Weather Report Service.
*
*/
@Service
public class WeatherReportServiceImpl implements WeatherReportService {
@Override
public Weather getDataByCityId(String cityId) {
// TODO 改为由天气数据API微服务来提供
Weather data = new Weather();
data.setAqi("81");
data.setCity("深圳");
data.setGanmao("容易感冒!多穿衣");
data.setWendu("22");
List<Forecast> forecastList = new ArrayList<>();
Forecast forecast = new Forecast();
forecast.setDate("25日星期天");
forecast.setType("晴");
forecast.setFengxiang("无风");
forecast.setHigh("高温 11度");
forecast.setLow("低温 1度");
forecastList.add(forecast);
forecast = new Forecast();
forecast.setDate("26日星期天");
forecast.setType("晴");
forecast.setFengxiang("无风");
forecast.setHigh("高温 11度");
forecast.setLow("低温 1度");
forecastList.add(forecast);
forecast = new Forecast();
forecast.setDate("27日星期天");
forecast.setType("晴");
forecast.setFengxiang("无风");
forecast.setHigh("高温 11度");
forecast.setLow("低温 1度");
forecastList.add(forecast);
forecast = new Forecast();
forecast.setDate("28日星期天");
forecast.setType("晴");
forecast.setFengxiang("无风");
forecast.setHigh("高温 11度");
forecast.setLow("低温 1度");
forecastList.add(forecast);
forecast = new Forecast();
forecast.setDate("29日星期天");
forecast.setType("晴");
forecast.setFengxiang("无风");
forecast.setHigh("高温 11度");
forecast.setLow("低温 1度");
forecastList.add(forecast);
data.setForecast(forecastList);
return data;
}
}
由于要调用天气数据微服务 先伪造数据实现
3.城市数据API微服务的实现 获取城市列表 读xml
单体项目-------------------》msa-weather-city-server
获取城市列表的COntroller
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.waylau.spring.cloud.weather.service.CityDataService;
import com.waylau.spring.cloud.weather.vo.City;
/**
* Hello Controller.
*
*/
@RestController
@RequestMapping("/cities")
public class CityController {
@Autowired
private CityDataService cityDataService;
@GetMapping
public List<City> listCity() throws Exception {
return cityDataService.listCity();
}
}
其实现
import java.util.List;
import com.waylau.spring.cloud.weather.vo.City;
/**
* City Data Service.
*
*/
public interface CityDataService {
/**
* 获取City列表
* @return
* @throws Exception
*/
List<City> listCity() throws Exception;
}
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.
*
*/
@Service
public class CityDataServiceImpl implements CityDataService {
@Override
public List<City> 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();
}
}
4.天气数据API微服务的实现 提供了天气数据的查询 用户查询(被天气预报微服务调用 得到数据)
只涉及数据查询
单体项目-------------------》msa-weather-data-server
利用redis
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.
*
*/
@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);
}
}
service部分
import com.waylau.spring.cloud.weather.vo.WeatherResponse;
/**
* Weather Data Service.
*
*/
public interface WeatherDataService {
/**
* 根据城市ID查询天气数据
*
* @param cityId
* @return
*/
WeatherResponse getDataByCityId(String cityId);
/**
* 根据城市名称查询天气数据
*
* @param cityId
* @return
*/
WeatherResponse getDataByCityName(String cityName);
}
实现
import java.io.IOException;
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.stereotype.Service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.waylau.spring.cloud.weather.vo.WeatherResponse;
/**
* WeatherDataService 实现.
*
*/
@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?";
@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<String, String> ops = stringRedisTemplate.opsForValue();
// 先查缓存,缓存有的取缓存中的数据
if (stringRedisTemplate.hasKey(key)) {
logger.info("Redis has data");
strBody = ops.get(key);
} else {
logger.info("Redis don't has data");
// 缓存没有,抛出异常
throw new RuntimeException("Don't has data!");
}
try {
resp = mapper.readValue(strBody, WeatherResponse.class);
} catch (IOException e) {
//e.printStackTrace();
logger.error("Error!",e);
}
return resp;
}
}
哈哈哈 终于拆分完了