我们做的这一系列的工作,其实目的就是为了将我们的服务进行拆分成微服务,我们可以简单看一下这个系统,它集成了数据采集,数据缓存,提供查询天气等功能,但是唯一的不足之处,耦合性太高,缺少业务上的隔离,一旦第三方采集的接口协议变化或者缓存服务down掉;都会影响到整个应用,所以,我们开始拆分服务,采用微服务的方式。
针对这个天气预报系统我们可以拆分成四个微服务:分别为:
天气数据采集微服务(springBoot-collection)
天气数据API微服务(springBoot-data)
城市数据API微服务(springBoot-city)
天气预报微服务(springBoot-report)
天气数据采集微服务(springBoot-collection)
项目:
CityClient这个接口现在不需要放在这里,后面才会用到。
pom文件:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.csq.study</groupId>
<artifactId>springBoot-collection</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-quartz -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
配置类 config
package com.yian.springboot.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;
/**
* 配置类
* @Description: TODO
* @ClassName: RestConfiguration
* @author csq 2019年2月28日 上午10:25:38
* @see TODO
*/
@Configuration
public class RestConfiguration {
@Autowired
private RestTemplateBuilder builder;
@Bean
public RestTemplate restTemplate(){
return builder.build();
}
}
job类
package com.yian.springboot.job;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.yian.springboot.service.WeatherDataCollectionService;
import com.yian.springboot.vo.City;
@Component
public class ScheduledTasks {
private static final Logger logger = LoggerFactory.getLogger(ScheduledTasks.class);
private static final SimpleDateFormat formate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Autowired
private WeatherDataCollectionService weatherDataCollectionService;
@Scheduled(fixedRate = 30000)
public void scheduledDemo(){
logger.info("天气数据同步任务 开始 every 5 seconds:{}", formate.format(new Date()) );
List<City> cityList=null;
try {
//此处因为还需要另外一个微服务提供,所以为了演示本微服务 我们暂且写死,后面会进行修改
cityList = new ArrayList<City>();
City city=new City();
city.setCityId("101010100");
cityList.add(city);
} catch (Exception e) {
logger.info("获取异常",e);
}
for (City city : cityList) {
String cityId = city.getCityId();
logger.info("天气任务同步中,cityId:"+cityId);
//根据城市id获取天气
weatherDataCollectionService.syncDataByCityId(cityId);
}
logger.info("天气任务同步End");
}
}
service接口和实现类
package com.yian.springboot.service;
public interface WeatherDataCollectionService {
/**
* 根据城市Id同步天气数据
* @Title: syncDataByCityId
* @Description: TODO
* @param cityId
* @author csq 2019年6月4日 下午2:35:52
*/
void syncDataByCityId(String cityId);
}
实现类:
package com.yian.springboot.service;
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;
/**
*
* @Description: 天气数据采集服务
* @ClassName: WeatherDataCollectionServiceImpl
* @author csq 2019年6月4日 下午2:37:25
* @see TODO
*/
@Service
public class WeatherDataCollectionServiceImpl implements WeatherDataCollectionService {
private final static Logger logger=LoggerFactory.getLogger(WeatherDataCollectionServiceImpl.class);
@Autowired
private RestTemplate restTemplate;
@Autowired
private StringRedisTemplate stringRedisTemplate;
private final String WEATHER_API="http://wthrcdn.etouch.cn/weather_mini";
//设置超时时间
private final Long TIME_OUT=1800L;
@Override
public void syncDataByCityId(String cityId) {
logger.info("Start 同步天气 .cityId"+cityId);
String uri = WEATHER_API + "?citykey=" + cityId;
this.saveWeatherData(uri);
logger.info("End 同步天气");
}
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);
//将接口返回的Json字符串转换成对象
if (respString.getStatusCodeValue() == 200) {
strBody = respString.getBody();
}
//数据写入缓存
ops.set(key,strBody,TIME_OUT, TimeUnit.SECONDS);
}
}
vo类
package com.yian.springboot.vo;
public class City{
private String cityId;
private String cityName;
private String cityCode;
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;
}
@Override
public String toString() {
return "City [cityId=" + cityId + ", cityName=" + cityName + ", cityCode=" + cityCode + ", province="
+ province + "]";
}
}
配置文件
启动类:
package com.yian.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class Aplication {
public static void main(String[] args) {
SpringApplication.run(Aplication.class, args);
}
}
在启动程序之前别忘记启动你的redis哦。
启动程序:看到如下截图就成功了。