SpringCloud服務消費的幾種方式

以下示例代碼均基於consul註冊中心

一、使用LoadBalancerClient

LoadBalancerClient接口的命名中,可以看出這是一個負載均衡客戶端的抽象定義,spring提供了一個實現
org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient

1、pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.wzl.springcloud</groupId>
	<artifactId>services-cousmer</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>services-consume</name>
	<description>Demo project for Spring Boot</description>
	
	<properties>
		<!-- 版本管理 -->
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<junit.version>4.12</junit.version>
		<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
	</properties>
	
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.7.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>	
			<artifactId>spring-cloud-starter-consul-discovery</artifactId>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.47</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- spring boot test -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>junit</groupId>
				<artifactId>junit</artifactId>
				<version>${junit.version}</version>
				<scope>test</scope>
			</dependency>

			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
	
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

2、application.yml

server: 
  #服務端口號
  port: 8080
spring: 
  application: 
    #服務名稱
    name: services-consume
  thymeleaf: 
    cache: false
  cloud:
    consul: 
      host: 192.168.12.125 
      port: 8500
      discovery: 
        #是否需要註冊到consul中
        register: true
        #服務地址直接爲IP地址
        hostname: 192.168.12.1
management:
  endpoints:
    web:
      exposure:
        include: '*'

3、啓動類

package com.wzl.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class ServicesConsumeApplication {
	
	public static void main(String[] args) {
		SpringApplication.run(ServicesConsumeApplication.class, args);
	}

}

4、相關實現類

package com.wzl.springcloud.basic.report.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.wzl.springcloud.basic.report.service.WeatherReportService;
import com.wzl.springcloud.basic.report.vo.City;

@RestController
public class ReportController {
	
	@Autowired
	private WeatherReportService weatherReportService;

	@RequestMapping("/report/getDataByCities")
	public List<City> getDataByCities() {
		return weatherReportService.getDataByCities();
	}

}
package com.wzl.springcloud.basic.report.vo;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

//聲明爲xml的根元素
@XmlRootElement(name = "d")
// 聲明xml的訪問類型爲FIELD(字段)
@XmlAccessorType(XmlAccessType.FIELD)
public class City {

	// 聲明爲xml的屬性
	@XmlAttribute(name = "d1")
	private String cityId;
	// 聲明爲xml的屬性
	@XmlAttribute(name = "d2")
	private String cityName;
	// 聲明爲xml的屬性
	@XmlAttribute(name = "d3")
	private String cityCode;
	// 聲明爲xml的屬性
	@XmlAttribute(name = "d4")
	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;
	}

}
package com.wzl.springcloud.basic.report.service;

import java.util.List;

import com.wzl.springcloud.basic.report.vo.City;

public interface WeatherReportService {

	// 獲取所有城市列表
	List<City> getDataByCities();
	
}

package com.wzl.springcloud.basic.report.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSON;
import com.wzl.springcloud.basic.report.service.WeatherReportService;
import com.wzl.springcloud.basic.report.vo.City;

/**
 * LoadBalancer客戶端
 */
@Service
public class WeatherReportServiceImpl implements WeatherReportService {

	@Autowired
	private LoadBalancerClient loadBalancer;

	// 城市服務的服務名
	private static final String CITY_SERVICE_NAME = "vis-basic-city";

	@Override
	public List<City> getDataByCities() {
		List<City> cityList = null;
		ServiceInstance serviceInstance = loadBalancer.choose(CITY_SERVICE_NAME);
		String uri = serviceInstance.getUri().toString() + "/cities/getList";
		// 調用服務接口來獲取
		ResponseEntity<String> respString = new RestTemplate().getForEntity(uri, String.class);
		// 判斷ResponseEntity的狀態碼是否爲200,爲200時取出strBody
		if (respString.getStatusCodeValue() == 200) {
			String jsonStr = respString.getBody();
			cityList = JSON.parseArray(jsonStr, City.class);
		}
		return cityList;
	}

}

測試訪問

二、使用Ribbon

Spring Cloud Ribbon是基於Netflix Ribbon實現的一套客戶端負載均衡的工具。它是一個基於HTTP和TCP的客戶端負載均衡器。它可以通過在客戶端中配置ribbonServerList來設置服務端列表去輪詢訪問以達到均衡負載的作用。

1、pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.wzl.springcloud</groupId>
	<artifactId>services-cousmer</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>services-consume</name>
	<description>Demo project for Spring Boot</description>
	
	<properties>
		<!-- 版本管理 -->
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<junit.version>4.12</junit.version>
		<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
	</properties>
	
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.7.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>	
			<artifactId>spring-cloud-starter-consul-discovery</artifactId>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.47</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- spring boot test -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
	</dependencies>
	
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>junit</groupId>
				<artifactId>junit</artifactId>
				<version>${junit.version}</version>
				<scope>test</scope>
			</dependency>

			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
	
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

2、application.yml

server: 
  #服務端口號
  port: 8080
spring: 
  application: 
    #服務名稱
    name: services-consume
  thymeleaf: 
    cache: false
  cloud:
    consul: 
      host: 192.168.12.125 
      port: 8500
      discovery: 
        #是否需要註冊到consul中
        register: true
        #服務地址直接爲IP地址
        hostname: 192.168.12.1
management:
  endpoints:
    web:
      exposure:
        include: '*'

3、啓動類 & RestConfiguration

package com.wzl.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class ServicesConsumeApplication {

	public static void main(String[] args) {
		SpringApplication.run(ServicesConsumeApplication.class, args);
	}

}
package com.wzl.springcloud.basic.report.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestConfiguration {

	@Autowired
	private RestTemplateBuilder builder;

	@Bean
	@LoadBalanced
	public RestTemplate restTemplate() {
		return builder.build();
	}

}

@LoadBalanced註解表明這個restRemplate開啓負載均衡的功能,用LoadBalancerClient配置,並且會替換URL中的服務名稱爲具體的IP地址

4、相關實現類

package com.wzl.springcloud.basic.report.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.wzl.springcloud.basic.report.service.WeatherReportService;
import com.wzl.springcloud.basic.report.vo.City;

@RestController
public class ReportController {
	
	@Autowired
	private WeatherReportService weatherReportService;

	@RequestMapping("/report/getDataByCities")
	public List<City> getDataByCities() {
		return weatherReportService.getDataByCities();
	}

}
package com.wzl.springcloud.basic.report.vo;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

//聲明爲xml的根元素
@XmlRootElement(name = "d")
// 聲明xml的訪問類型爲FIELD(字段)
@XmlAccessorType(XmlAccessType.FIELD)
public class City {

	// 聲明爲xml的屬性
	@XmlAttribute(name = "d1")
	private String cityId;
	// 聲明爲xml的屬性
	@XmlAttribute(name = "d2")
	private String cityName;
	// 聲明爲xml的屬性
	@XmlAttribute(name = "d3")
	private String cityCode;
	// 聲明爲xml的屬性
	@XmlAttribute(name = "d4")
	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;
	}

}
package com.wzl.springcloud.basic.report.service;

import java.util.List;

import com.wzl.springcloud.basic.report.vo.City;

public interface WeatherReportService {

	// 獲取所有城市列表
	List<City> getDataByCities();

}
package com.wzl.springcloud.basic.report.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSON;
import com.wzl.springcloud.basic.report.service.WeatherReportService;
import com.wzl.springcloud.basic.report.vo.City;

/**
 * Ribbon客戶端
 */
@Service
public class WeatherReportServiceImpl implements WeatherReportService {

	@Autowired
	// 對rest客戶端的封裝
	private RestTemplate restTemplate;

	// 城市服務的服務名
	private static final String CITY_SERVICE_NAME = "vis-basic-city";

	@Override
	public List<City> getDataByCities() {
		List<City> cityList = null;
		String uri = "http://" + CITY_SERVICE_NAME + "/cities/getList";
		// 調用服務接口來獲取
		ResponseEntity<String> respString = restTemplate.getForEntity(uri, String.class);
		// 判斷ResponseEntity的狀態碼是否爲200,爲200時取出strBody
		if (respString.getStatusCodeValue() == 200) {
			String jsonStr = respString.getBody();
			cityList = JSON.parseArray(jsonStr, City.class);
		}
		return cityList;
	}

}

測試訪問

三、使用Feign

Feign是一個聲明性的web服務客戶端,它使編寫web服務客戶機變得更容易。
總結特點:
1、Feign採用的是接口加註解,就像調用本地方法一樣調用遠程服務
2、Feign整合了Ribbon,當你使用@FeignClient,Ribbon自動被應用,所以也會負載均衡
3、Feign是一種聲明式、模板化的HTTP客戶端。

1、pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.wzl.springcloud</groupId>
	<artifactId>services-cousmer</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>services-consume</name>
	<description>Demo project for Spring Boot</description>
	
	<properties>
		<!-- 版本管理 -->
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<junit.version>4.12</junit.version>
		<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
	</properties>
	
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.7.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>	
			<artifactId>spring-cloud-starter-consul-discovery</artifactId>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.47</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- spring boot test -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-openfeign</artifactId>
		</dependency>
	</dependencies>
	
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>junit</groupId>
				<artifactId>junit</artifactId>
				<version>${junit.version}</version>
				<scope>test</scope>
			</dependency>

			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
	
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

2、application.yml

server: 
  #服務端口號
  port: 8080
spring: 
  application: 
    #服務名稱
    name: services-consume
  thymeleaf: 
    cache: false
  cloud:
    consul: 
      host: 192.168.12.125 
      port: 8500
      discovery: 
        #是否需要註冊到consul中
        register: true
        #服務地址直接爲IP地址
        hostname: 192.168.12.1
management:
  endpoints:
    web:
      exposure:
        include: '*'

3、啓動類

package com.wzl.springcloud.basic.report;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients
public class ReportServerApplication {
	
	public static void main(String[] args) {
		SpringApplication.run(ReportServerApplication.class, args);
	}

}

4、相關實現類

package com.wzl.springcloud.basic.report.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.wzl.springcloud.basic.report.service.WeatherReportService;
import com.wzl.springcloud.basic.report.vo.City;

@RestController
public class ReportController {
	
	@Autowired
	private WeatherReportService weatherReportService;

	@RequestMapping("/report/getDataByCities")
	public List<City> getDataByCities() {
		return weatherReportService.getDataByCities();
	}

}
package com.wzl.springcloud.basic.report.vo;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

//聲明爲xml的根元素
@XmlRootElement(name = "d")
// 聲明xml的訪問類型爲FIELD(字段)
@XmlAccessorType(XmlAccessType.FIELD)
public class City {

	// 聲明爲xml的屬性
	@XmlAttribute(name = "d1")
	private String cityId;
	// 聲明爲xml的屬性
	@XmlAttribute(name = "d2")
	private String cityName;
	// 聲明爲xml的屬性
	@XmlAttribute(name = "d3")
	private String cityCode;
	// 聲明爲xml的屬性
	@XmlAttribute(name = "d4")
	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;
	}

}
package com.wzl.springcloud.basic.report.feign;

import java.util.List;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;

import com.wzl.springcloud.basic.report.vo.City;

@FeignClient(name = "vis-basic-city")
@RequestMapping("/cities")
public interface CityApiFeign {

	@RequestMapping("/getList")
	public List<City> listCity();

}
package com.wzl.springcloud.basic.report.service;

import java.util.List;

import com.wzl.springcloud.basic.report.vo.City;

public interface WeatherReportService {

	// 獲取所有城市列表
	List<City> getDataByCities();

}
package com.wzl.springcloud.basic.report.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.wzl.springcloud.basic.report.feign.CityApiFeign;
import com.wzl.springcloud.basic.report.service.WeatherReportService;
import com.wzl.springcloud.basic.report.vo.City;


/**
 * Feign客戶端
 */
@Service
public class WeatherReportServiceImpl implements WeatherReportService {
	
	@Autowired
	private CityApiFeign cityApiFeign;
	
	@Override
	public List<City> getDataByCities() {
		return cityApiFeign.listCity();
	}

}

測試訪問

四、通過網關調用服務

在微服務框架中,每個對外服務都是獨立部署的,對外的API或者服務地址都不是不盡相同的。對於內部而言,很簡單,通過註冊中心自動感知即可。但我們大部分情況下,服務都是提供給外部系統進行調用的,不可能同享一個註冊中心。同時一般上內部的微服務都是在內網的,和外界是不連通的。而且,就算我們每個微服務對外開放,對於調用者而言,調用不同的服務的地址或者參數也是不盡相同的,這樣就會造成消費者客戶端的複雜性,同時想想,可能微服務可能是不同的技術棧實現的,有的是http、rpc或者websocket等等,也會進一步加大客戶端的調用難度。所以,一般上都有會有個api網關,根據請求的url不同,路由到不同的服務上去,同時入口統一了,還能進行統一的身份鑑權、日誌記錄、分流等操作。接下來就是基於zuul的服務調用。

需要提前搭建好網關服務,以下示例代碼基於zuul網關

1、網關zuul的application.yml配置

server: 
  #服務端口號 
  port: 7070
spring: 
  application: 
    #服務的名稱
    name: vis-basic-zuul
  #指定註冊中心地址
  cloud: 
    consul: 
      host: 192.168.12.125
      port: 8500
      discovery: 
        #是否需要註冊到consul中
        register: true
        #服務地址直接爲IP地址
        hostname: 192.168.12.1
        service-name: ${spring.application.name}      
        healthCheckPath: /actuator/health
        healthCheckInterval: 15s
        
zuul: 
  #表示不暴露配置之外的服務
  ignored-services: '*'
  routes: 
    #天氣服務
    vis-basic-weather: 
      path: /api-weather/**
      service-id: vis-basic-weather
      
    #城市服務
    vis-basic-city: 
      path: /api-city/**
      service-id: vis-basic-city
      

2、pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.wzl.springcloud</groupId>
	<artifactId>services-cousmer</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>services-consume</name>
	<description>Demo project for Spring Boot</description>
	
	<properties>
		<!-- 版本管理 -->
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<junit.version>4.12</junit.version>
		<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
	</properties>
	
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.7.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>	
			<artifactId>spring-cloud-starter-consul-discovery</artifactId>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.47</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- spring boot test -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-openfeign</artifactId>
		</dependency>
	</dependencies>
	
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>junit</groupId>
				<artifactId>junit</artifactId>
				<version>${junit.version}</version>
				<scope>test</scope>
			</dependency>

			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
	
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

3、application.yml

server: 
  #服務端口號
  port: 8080
spring: 
  application: 
    #服務名稱
    name: services-consume
  thymeleaf: 
    cache: false
  cloud:
    consul: 
      host: 192.168.12.125 
      port: 8500
      discovery: 
        #是否需要註冊到consul中
        register: true
        #服務地址直接爲IP地址
        hostname: 192.168.12.1
management:
  endpoints:
    web:
      exposure:
        include: '*'
  

4、啓動類

package com.wzl.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients
public class ServicesConsumeApplication {
	
	public static void main(String[] args) {
		SpringApplication.run(ServicesConsumeApplication.class, args);
	}

}

5、相關實現類

package com.wzl.springcloud.basic.report.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.wzl.springcloud.basic.report.service.WeatherReportService;
import com.wzl.springcloud.basic.report.vo.City;

@RestController
public class ReportController {
	
	@Autowired
	private WeatherReportService weatherReportService;

	@RequestMapping("/report/getDataByCities")
	public List<City> getDataByCities() {
		return weatherReportService.getDataByCities();
	}

}
package com.wzl.springcloud.basic.report.vo;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

//聲明爲xml的根元素
@XmlRootElement(name = "d")
// 聲明xml的訪問類型爲FIELD(字段)
@XmlAccessorType(XmlAccessType.FIELD)
public class City {

	// 聲明爲xml的屬性
	@XmlAttribute(name = "d1")
	private String cityId;
	// 聲明爲xml的屬性
	@XmlAttribute(name = "d2")
	private String cityName;
	// 聲明爲xml的屬性
	@XmlAttribute(name = "d3")
	private String cityCode;
	// 聲明爲xml的屬性
	@XmlAttribute(name = "d4")
	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;
	}

}
package com.wzl.springcloud.basic.report.feign;

import java.util.List;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;

import com.wzl.springcloud.basic.report.vo.City;

@FeignClient(name = "vis-basic-zuul")
@RequestMapping("/api-city/cities")
public interface CityApiFeignGateway {

	@RequestMapping("/getList")
	public List<City> listCity();

}
package com.wzl.springcloud.basic.report.service;

import java.util.List;

import com.wzl.springcloud.basic.report.vo.City;

public interface WeatherReportService {

	// 獲取所有城市列表
	List<City> getDataByCities();

}
package com.wzl.springcloud.basic.report.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.wzl.springcloud.basic.report.feign.CityApiFeignGateway;
import com.wzl.springcloud.basic.report.service.WeatherReportService;
import com.wzl.springcloud.basic.report.vo.City;


/**
 * FeignGateway客戶端
 */
@Service
public class WeatherReportServiceImpl implements WeatherReportService {
	
	@Autowired
	private CityApiFeignGateway cityApiFeignGateway;
	
	@Override
	public List<City> getDataByCities() {
		return cityApiFeignGateway.listCity();
	}

}

測試訪問

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章