回顾遗留的三个TODO
- 数据采集微服务在天气数据同步任务中,依赖于城市数据API微服务
- 天气预报微服务查询天气信息,依赖于天气数据API微服务
- 天气预报微服务提供的城市列表,依赖于城市数据API微服务
天气预报系统微服务使用Feign
msa-weather-collection-eureka-feign
创建项目
复制之前的msa-weather-collection-eureka
项目,将副本改名为msa-weather-collection-eureka-feign
修改源码
修改build.gradle
配置,添加Feign
依赖:
//依赖关系
dependencies {
//该依赖用于编译阶段
compile('org.springframework.boot:spring-boot-starter-web')
//HttpClient
compile('org.apache.httpcomponents:httpclient:4.5.6')
//Redis
compile('org.springframework.boot:spring-boot-starter-data-redis')
//Quartz
compile('org.springframework.boot:spring-boot-starter-quartz')
//Eureka Client
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
//Feign
compile('org.springframework.cloud:spring-cloud-starter-openfeign:2.0.0.M3')
//该依赖用于测试阶段
testCompile('org.springframework.boot:spring-boot-starter-test')
}
修改com.study.spring.cloud.weather
包下的Application
类,加入@EnableFeignClients
注解:
package com.study.spring.cloud.weather;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
/*
* @SpringBootApplication注解声明Spring Boot应用
* 作用等同于@Configuration, @EnableAutoConfiguration, @ComponentScan,
* 简化Spring配置
*/
@SpringBootApplication
//启用可发现的客户端
@EnableDiscoveryClient
//启用Feign
@EnableFeignClients
//Application类一定要处于整个工程的根目录下,这样它才能根据配置去扫描子节点下的Spring的Bean
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
在com.study.spring.cloud.weather.service
包下新建接口CityClient
:
package com.study.spring.cloud.weather.service;
import com.study.spring.cloud.weather.vo.City;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.List;
@FeignClient("msa-weather-city-eureka")
public interface CityClient {
@GetMapping("/cities")
List<City> listCity() throws Exception;
}
修改com.study.spring.cloud.weather.job
包下的WeatherDataSyncJob
类:
package com.study.spring.cloud.weather.job;
import com.study.spring.cloud.weather.service.CityClient;
import com.study.spring.cloud.weather.service.WeatherDataCollectionService;
import com.study.spring.cloud.weather.vo.City;
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 java.util.List;
public class WeatherDataSyncJob extends QuartzJobBean {
//在应用中添加日志
private final static Logger logger=LoggerFactory.getLogger(WeatherDataCollectionService.class);
@Autowired
private WeatherDataCollectionService weatherDataCollectionService;
@Autowired
private CityClient cityClient;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
logger.info("Weather Data Sync Job. Start!");
//获取城市列表
List<City> cityList=null;
try {
//由城市数据API微服务来提供数据
cityList = cityClient.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);
weatherDataCollectionService.syncDataByCityId(cityId);
}
logger.info("Weather Data Sync Job. End!");
}
}
修改application.properties
配置文件:
#应用名称
spring.application.name=msa-weather-collection-eureka-feign
#注册服务器的URL
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
#请求服务时的超时时间
feign.client.config.feignName.connect-timeout=5000
#读数据时的超时时间
feign.client.config.feignName.read-timeout=5000
msa-weather-report-eureka-feign
创建项目
复制之前的msa-weather-report-eureka
项目,将副本改名为msa-weather-report-eureka-feign
修改源码
修改build.gradle
配置,添加Feign
依赖:
//依赖关系
dependencies {
//该依赖用于编译阶段
compile('org.springframework.boot:spring-boot-starter-web')
//添加Spring Boot Thymeleaf Starter的依赖
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
//Eureka Client
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
//Feign
compile('org.springframework.cloud:spring-cloud-starter-openfeign:2.0.0.M3')
//该依赖用于测试阶段
testCompile('org.springframework.boot:spring-boot-starter-test')
}
修改com.study.spring.cloud.weather
包下的Application
类,加入@EnableFeignClients
注解:
package com.study.spring.cloud.weather;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
/*
* @SpringBootApplication注解声明Spring Boot应用
* 作用等同于@Configuration, @EnableAutoConfiguration, @ComponentScan,
* 简化Spring配置
*/
@SpringBootApplication
//启用可发现的客户端
@EnableDiscoveryClient
//启用Feign
@EnableFeignClients
//Application类一定要处于整个工程的根目录下,这样它才能根据配置去扫描子节点下的Spring的Bean
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
在com.study.spring.cloud.weather.service
包下新建接口CityClient
:
package com.study.spring.cloud.weather.service;
import com.study.spring.cloud.weather.vo.City;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.List;
@FeignClient("msa-weather-city-eureka")
public interface CityClient {
@GetMapping("/cities")
List<City> listCity() throws Exception;
}
在com.study.spring.cloud.weather.service
包下新建接口WeatherDataClient
:
package com.study.spring.cloud.weather.service;
import com.study.spring.cloud.weather.vo.WeatherResponse;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient("msa-weather-data-eureka")
public interface WeatherDataClient {
@GetMapping("/weather/cityId/{cityId}")
WeatherResponse getDataByCityId(@PathVariable("cityId") String cityId);
}
修改com.study.spring.cloud.weather.service
包下的WeatherReportServiceImpl
类:
package com.study.spring.cloud.weather.service;
import com.study.spring.cloud.weather.vo.Weather;
import com.study.spring.cloud.weather.vo.WeatherResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class WeatherReportServiceImpl implements WeatherReportService {
@Autowired
private WeatherDataClient weatherDataClient;
@Override
public Weather getDataByCityId(String cityId) {
//由天气数据API微服务来提供数据
WeatherResponse resp=weatherDataClient.getDataByCityId(cityId);
Weather data=resp.getData();
return data;
}
}
修改com.study.spring.cloud.weather.controller
包下的WeatherReportController
类:
package com.study.spring.cloud.weather.controller;
import com.study.spring.cloud.weather.service.CityClient;
import com.study.spring.cloud.weather.service.WeatherReportService;
import com.study.spring.cloud.weather.vo.City;
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 java.util.List;
@RestController
@RequestMapping("/report")
public class WeatherReportController {
//在应用中添加日志
private final static Logger logger=LoggerFactory.getLogger(WeatherReportController.class);
@Autowired
private WeatherReportService weatherReportService;
@Autowired
private CityClient cityClient;
@GetMapping("/cityId/{cityId}")
//@PathVariable:标识从路径中获取参数
public ModelAndView getReportByCityId(@PathVariable("cityId") String cityId,Model model) throws Exception {
//获取城市列表
List<City> cityList=null;
try {
//由城市数据API微服务来提供数据
cityList = cityClient.listCity();
} 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);
}
}
修改application.properties
配置文件:
#热部署静态文件
spring.thymeleaf.cache=false
#应用名称
spring.application.name=msa-weather-report-eureka-feign
#注册服务器的URL
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
#请求服务时的超时时间
feign.client.config.feignName.connect-timeout=5000
#读数据时的超时时间
feign.client.config.feignName.read-timeout=5000
运行微服务实例
注意要先运行Redis
java -jar micro-weather-eureka-server-1.0.0.jar --server.port=8761
java -jar msa-weather-collection-eureka-feign-1.0.0.jar --server.port=8081
java -jar msa-weather-collection-eureka-feign-1.0.0.jar --server.port=8082
java -jar msa-weather-data-eureka-1.0.0.jar --server.port=8083
java -jar msa-weather-data-eureka-1.0.0.jar --server.port=8084
java -jar msa-weather-city-eureka-1.0.0.jar --server.port=8085
java -jar msa-weather-city-eureka-1.0.0.jar --server.port=8086
java -jar msa-weather-report-eureka-feign-1.0.0.jar --server.port=8087
java -jar msa-weather-report-eureka-feign-1.0.0.jar --server.port=8088
访问http://localhost:8761
页面,可以看到Eureka
的管理页面:
访问http://localhost:8088/report/cityId/101020100
页面:
在页面中切换选中城市: