照例附上项目github连接java
本项目实现的是将一个简单的天气预报系统一步一步改形成一个SpringCloud微服务系统的过程。本章主要讲解API网关。git
在目前的项目中咱们构建了许多的API微服务,当第三方服务想要调用咱们的API微服务的时候是经过微服务的名称进行调用的,没有一个统一的入口。github
API网关就是为了统一服务的入口,能够方便地实现对平台的众多服务接口进行管控,对访问服务的身份进行验证,防止数据的篡改等。web
咱们的一个微服务可能须要依赖多个API微服务,API网关能够在中间作一个api的汇集。spring
那么咱们的微服务只须要统一地通过API网关就能够了(只须要依赖于API网关就能够了),不用关心各类API微服务的细节,须要调用的API微服务由API网关来进行转发。后端
Zuul是Netflix开源的微服务网关,他能够和Eureka,Ribbon,Hystrix等组件配合使用。Zuul组件的核心是一系列的过滤器,这些过滤器能够完成如下功能:api
Spring Cloud对Zuul进行了整合和加强。目前,Zuul使用的默认是Apache的HTTP Client,也可使用Rest Client,能够设置ribbon.restclient.enabled=true。跨域
在原来项目的基础上,建立一个msa-weather-eureka-client-zuul做为API网关。安全
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency>
添加@EnableZuulProxy启用Zuul的代理功能。架构
@SpringBootApplication @EnableDiscoveryClient @EnableZuulProxy public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
这里配置的是设置路由的url。
当有人访问 /city/ 路径的时候,就对访问这个路径的请求作一个转发,转发到msa-weather-city-eureka服务中去,同理,当有人访问 /data/ 路径的时候,API网关也会将这个请求转发到msa-weather-data-eureka服务中去。
zuul: routes: city: path: /city/** service-id: msa-weather-city-eureka data: path: /data/** service-id: msa-weather-data-eureka
原来天气预报微服务依赖了城市数据API微服务,以及天气数据API微服务,这里咱们对其进行修改让其依赖API网关,让API网关处理天气预报微服务其余两个微服务的调用。
首先删去原来调用其余两个API微服务的Feign客户端——CityClient以及WeatherDataClient,建立一个新的Feign客户端——DataClient。
package com.demo.service; import java.util.List; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import com.demo.vo.City; import com.demo.vo.WeatherResponse; @FeignClient("msa-weather-eureka-client-zuul") public interface DataClient { //获取城市列表 @RequestMapping(value="/city/cities",method=RequestMethod.GET) List<City> listCity()throws Exception; //经过城市Id查询对应城市的天气数据 @RequestMapping(value="/data/weather/cityId",method=RequestMethod.GET) WeatherResponse getDataByCityId(@RequestParam("cityId")String cityId); }
在service中使用该客户端对API网关进行调用,API网关根据咱们请求的路径去调用相应的微服务。
@Service public class WeatherReportServiceImpl implements WeatherReportService{ //@Autowired //private WeatherDataClient weatherDataClient; @Autowired private DataClient dataClient; //根据城市Id获取天气预报的数据 @Override public Weather getDataByCityId(String cityId) { //由天气数据API微服务来提供根据城市Id查询对应城市的天气的功能 WeatherResponse resp=dataClient.getDataByCityId(cityId); Weather data=resp.getData(); return data; } }
在controller也是同理。
//传入城市Id获得对应城市的天气数据 @GetMapping("/cityId/{cityId}") public Weather getReportByCityId(@PathVariable("cityId")String cityId,Model model)throws Exception{ //获取城市Id列表 //由城市数据API微服务来提供数据 List<City>cityList=null; try { cityList=dataClient.listCity(); }catch (Exception e) { logger.error("Exception!",e); } Weather weather=weatherReportService.getDataByCityId(cityId); return weather; }