大牛教你学微服务架构开发实战:使用Feign实现服务的消费者

2022-10-28 15:56:36 浏览数 (1)

使用Feign实现服务的消费者

我们在第7章已经将天气预报系统的所有功能都拆分为微服务。其中,也遗留了三个“TODO”项。

  • 天气数据采集微服务在天气数据同步任务中,依赖于城市数据API微服务。
  • 天气预报微服务查询天气信息,依赖于天气数据API微服务。
  • 天气预报微服务提供的城市列表,依赖于城市数据API微服务。

这三个“TODO”项都需要调用外部系统的API。在本节我们将通过使用Feign来实现调用外部的RESTful服务。

天气数据采集微服务使用Feign

作为演示,我们将基于老的天气数据采集微服务 msa-weather-collection-eureka进行修改,成为新的具备Feign功能的微服务msa-weather-collection-eureka-feign。

1.项目配置

为了使用Feign,在 build.gradle文件中增加如下配置。

代码语言:javascript复制
dependencies i
/l ...
//添加Spring Cloud Starter OpenFeign依赖
compile( 'org.springframework.cloud:spring-cloud-starter-openfeign')
}

2.启用Feign

要启用Feign,在应用的根目录的Application类上添加 org.springframework.cloud.netflix.fcign.EnableFeignClients注解即可。

代码语言:javascript复制
package com.waylau.spring.cloud.weather;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscovery
Client;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
*主应用程序.
*
*@since 1.o.0 2017年11月05日
* @author <a href="https://waylau.com">Way Lau</a>
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class Application{
public static void main(String [] args) {
SpringApplication.run(Application.class, args);
}

3.修改WeatherDataSyncJob

老的方法是伪造了一个城市数据。

代码语言:javascript复制
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("获取城市信息异常!",e);
throw new RuntimeException("获取城市信息异常!",e);
}

这里,我们将使用Feign来从城市数据API微服务msa-weather-city-cureka中获取城市的信息。

首先,我们要定义一个Feign客户端CityClient。

代码语言:javascript复制
package com.waylau.spring.cloud.weather.service;
import java.util.List;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import com.waylau.spring.cloud.weather.vo.City;
/*★
*访问城市信息的客户端.
*
*@since 1.0.0 2017年11月5日
* @author <a href="https://waylau.com">Way Lau</a>
*/
@FeignClient("msa-weather-city-eureka")
public interface CityClient {
@GetMapping("/cities")
List<City> listCity() throws Exception;
}

CityClient在@FeignClient注解中指定了需要访问的应用的名称。

其次,我们在需要获取外部服务的WeatherDataSyncJob类中,使用CityClient接口即可。

代码语言:javascript复制
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.CityClient;
import com.waylau.spring.cloud.weather.service.WeatherDataCollection
Service;
import com.waylau.spring.cloud.weather.vo.City;
/**
*天气数据同步任务.
*
*@since 1.o.o 2017年10月29日
* @author <a href="https://waylau.com">Way Lau</a>
*/
public class WeatherDataSyncJob extends QuartzJobBean
private final static Logger logger = LoggerFactory.getLogger(Weather
DataSyncJob .class);
Autowired
private WeatherDataCollectionService weatherDataCollectionService;
Autowired
private CityClient cityClient;
@override
protected void executeInternal (JobExecutionContext context) throws
JobExecutionException {
logger.info("Start天气数据同步任务");
//由城市数据API微服务来提供数据
List<City> cityList = null;
try {
//调用城市数据API
cityList = cityClient.listCity();
]catch(Exception e)
logger.error("获取城市信息异常!",e);
throw new RuntimeException("获取城市信息异常!",e);
}
for (City city :cityList){
String cityId= city.getcityId();
logger.info("天气数据同步任务中,cityid:"  cityId);
//根据城市ID同步天气数据
weatherDataCollectionService.syncDataByCityId(cityId);
logger.info("End 天气数据同步任务");
}
}

4.修改项目配置

最后,修改application.properties。将其修改为如下配置。

代码语言:javascript复制
spring.application.name: msa-weather-collection-eureka-feign
eureka.client.serviceUrl.defaultZone:http://localhost:8761/eureka/
feign.client.config.feignName.connectTimeout:5000
feign.client.config.feignName.readTimeout:5000

天气预报微服务使用Feign

的具备Feign功能的微服务 msa-weather-report-eureka-feign。

1.项目配置

为了使用Feign,在 build.gradle文件中增加如下配置。

代码语言:javascript复制
dependencies {
// ...
作为演示,我们将基于老的天气数据采集微服务msa-weather-report-cureka进行修改,成为新
//添加Spring Cloud starter OpenFeign依赖
compile('org.springframework.cloud:spring-cloud-starter-openfeign')
)

2.启用Feign

要启用Feign,在应用的根目录的Application类上添加 org.springframework.cloud.netflix.feign.EnableFeignClients注解即可。

代码语言:javascript复制
package com.waylau.spring.cloud.weather;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscovery
Client;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
**
*主应用程序.
*
*@since 1.o.0 2017年11月05日
* author <a href="https://waylau.com">Way Lau</a>
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class Application{
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}

3.定义Feign客户端

首先,我们要定义一个Feign客户端CityClient,来从城市数据API微服务msa-weather-city-eureka中获取城市的信息。

代码语言:javascript复制
package com.waylau.spring.cloud.weather.service;
import java.util.List;
import org.springframework.cloud.netflix.feign.Eeignclient;
import org.springframework.web.bind.annotation.GetMapping;
import com.waylau.spring.cloud.weather.vo.City;
/**
*访问城市信息的客户端.
*
@since 1.o.0 2017年11月5日
author <a href="https://waylau.com">Way Lau</a>
*/
@FeignClient( "msa-weather-city-eureka")
public interface CityClient{
@GetMapping("/cities")
List<City> listCity()throws Exception;
}

其次,我们再定义一个Feign客户端WeatherDataClient,来从天气数据API微服务msa-weather-data-eureka中获取天气的数据。

代码语言:javascript复制
package com.waylau.spring.cloud.weather.service;
import org.springframework.cloud.netflix.feign.FeignClient;
import com.waylau.spring.cloud.weather.vo.WeatherResponse;
★*
*访问天气数据的客户端.
*
*@since 1.o.02017年11月5日
*@author <a href="https://waylau.com">Way Lau/a>
*/
FeignClient( "msa-weather-data-eureka")
public interface WeatherDataclient {
/**
*根据城市ID查询天气数据
*
*@param cityId
*@return
*/
@GetMapping("/weather/cityId/{cityId}")
WeatherResponse getDataByCityId(@PathVariable("cityId") String
cityId);
}

4.修改天气预报服务

修改天气预报服务WeatherReportServicelmpl,将原有的仿造的数据改为从Feign客户端获取天气数据API微服务提供的数据。

代码语言:javascript复制
package com.waylau.spring.cloud.weather.service;
import org.springframework.beans.factory.annotation.Autowired;
irmport org.springframework.stereotype.Service;
import com.waylau.spring.cloud.weather.vo.Weather;
import com.waylau.spring.cloud.weather.vo.WeatherResponse;
**
*天气预报服务.
*
*@since 1.o.0 2017年11月05日
*@author <a href="https://waylau.com">Way Lau</a>
*/
@service
public class WeatherReportServiceimpl implements WeatherReportService{
Autowired
private WeatherDataClient weatherDataClient;
@override
public Weather getDataByCityId(String cityId)
//由天气数据AP工微服务来提供数据
WeatherResponse response = weatherDataclient.getDataByCityId
(cityId);
return response.getData(;
}

5.修改天气预报控制器

修改天气预报控制器WeatherReportController,将原有的伪造的城市数据改为由CityClient来获

取城市数据API微服务中的城市数据。

代码语言:javascript复制
package com.waylau.spring.cloud.weather.controller;
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.CityClient;
import com.waylau.spring.cloud.weather.service.WeatherReportService;
import com.waylau.spring.cloud.weather.vo.City;
/**
*天气预报API.
*
*@since 1.0.0 2017年10月29日
@author <a href="https://waylau.com" >Way Lau</a>
*/
RestController
@RequestMapping("/report")
public class WeatherReportController {
private final static Logger logger = LoggerFactory.getLogger(Weather
ReportController.class);
@Autowired  
private CityClient cityClient;
@Autowired
private WeatherReportService weatherReportService;
@GetMapping("/cityId/{cityId} ")
public ModelAndView getReportByCityId (@PathVariable ("cityId") String
cityId, Model model) throws Exception {
//由城市数据API微服务来提供数据
List<City> cityList =null;
try{
//调用城市数据API
cityList=cityClient.listCity();
}catch(Exception e)
logger.error("获取城市信息异常!",e);
throw new RuntimeException("获取城市信息异常!",e);
}
model.addAttribute("title","老卫的天气预报");
model.addAttribute("cityld",cityId);
model.addAttribute("cityList",cityList);
model.addAttribute ("report", weatherReportService.getDataBy
CityId(cityId));
return new ModelAndView("weather/report", "reportModel",
model);
}

6.修改项目配置

最后,修改application.properties。将其修改为如下配置。

代码语言:javascript复制
#热部署静态文件
spring.thymeleaf.cache=false
spring.application.name: msa-weather-report-eureka-feign
eureka.client.serviceUrl.defaultZone: http://localhost:8761/eureka/
feign.client.config.feignName.connectTimeout:5000
feign.client.config.feignName.readTimeout:5000

源码

本节示例所涉及的源码,见 micro-weather-eureka-server、msa-weather-data-eureka和msa-weather-city-eureka,以及msa-weather-collection-eureka-feign和 msa-weather-report-eureka-feign。

本篇文章内容给大家讲解的是使用Feign实现服务的消费者

  1. 下篇文章给大家讲解实现服务的负载均衡及高可用;
  2. 觉得文章不错的朋友可以转发此文关注小编;
  3. 感谢大家的支持

本文就是愿天堂没有BUG给大家分享的内容,大家有收获的话可以分享下,想学习更多的话可以到微信公众号里找我,我等你哦。

0 人点赞