Spring Cloud Eureka 服务发现

服务发现是基于微服务的体系结构的主要宗旨之一。 尝试手动配置每个客户端或某种形式的约定可能很困难并且很脆弱。 Eureka是Netflix Service Discovery服务器和客户端。 可以将服务器配置和部署为高可用性,每个服务器将有关已注册服务的状态复制到其他服务器。

1 构建Eureka服务器

要将Eureka Server包含在您的项目中,请使用组ID为org.springframework.cloud和工件ID为的启动器spring-cloud-starter-netflix-eureka-server。

pom.xml

    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>

application.yml

#Default port is 8761
server:
  port: 8761
eureka:
  client:
    registerWithEureka: false
    fetchRegistry: false
  server:
    waitTimeInMsWhenSyncEmpty: 5
  serviceUrl:
    defaultZone: http://localhost:8761

EurekaServerApplication.java

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

启动服务,访问http://localhost:8761/,查看服务界面,如下图所示:

2 通过Eureka注册服务

在MySQL数据库eagle_eye_local

创建organizations组织表

DROP TABLE IF EXISTS organizations;

CREATE TABLE organizations (
  organization_id        VARCHAR(100) PRIMARY KEY NOT NULL,
  name                   TEXT NOT NULL,
  contact_name           TEXT NOT NULL,
  contact_email          TEXT NOT NULL,
  contact_phone          TEXT   NOT NULL);


INSERT INTO organizations (organization_id, name, contact_name, contact_email, contact_phone)
VALUES ('e254f8c-c442-4ebe-a82a-e2fc1d1ff78a', 'customer-crm-co', 'Mark Balster', '[email protected]', '823-555-1212');

INSERT INTO organizations (organization_id, name, contact_name, contact_email, contact_phone)
VALUES ('442adb6e-fa58-47f3-9ca2-ed1fecdfe86c', 'HR-PowerSuite', 'Doug Drewry','[email protected]', '920-555-1212');

客户端向Eureka注册时,它会提供有关其自身的元数据,例如主机,端口,运行状况指示器URL,主页和其他详细信息。Eureka从属于服务的每个实例接收心跳消息。如果心跳在可配置的时间表上进行故障转移,则通常会将实例从注册表中删除。

创建一个Spring Boot微服务作为组织服务。

在pom.xml中增加以下依赖jar包:

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-config-client</artifactId>
		</dependency>

application.yml

spring:
  application:
    name: organizationservice
  profiles:
    active:
      dev
  cloud:
    config:
      enabled: true
server:
  port: 8181
eureka:
  instance:
    preferIpAddress: true
  client:
    registerWithEureka: true
    fetchRegistry: true
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

OrganizationServiceApplication.java

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

Organization.java

package com.example.organization.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "organizations")
public class Organization {
	@Id
	@Column(name = "organization_id", nullable = false)
	String id;

	@Column(name = "name", nullable = false)
	String name;

	@Column(name = "contact_name", nullable = false)
	String contactName;

	@Column(name = "contact_email", nullable = false)
	String contactEmail;

	@Column(name = "contact_phone", nullable = false)
	String contactPhone;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getContactName() {
		return contactName;
	}

	public void setContactName(String contactName) {
		this.contactName = contactName;
	}

	public String getContactEmail() {
		return contactEmail;
	}

	public void setContactEmail(String contactEmail) {
		this.contactEmail = contactEmail;
	}

	public String getContactPhone() {
		return contactPhone;
	}

	public void setContactPhone(String contactPhone) {
		this.contactPhone = contactPhone;
	}

}

OrganizationRepository.java

package com.example.organization.repository;

import com.example.organization.model.Organization;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

@Repository
public interface OrganizationRepository extends CrudRepository<Organization, String> {
	
	public Optional<Organization> findById(String organizationId);
	
}

OrganizationService.java

package com.example.organization.services;

import com.example.organization.model.Organization;
import com.example.organization.repository.OrganizationRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Optional;
import java.util.UUID;

@Service
public class OrganizationService {
	@Autowired
	private OrganizationRepository orgRepository;

	public Optional<Organization> getOrg(String organizationId) {
		return orgRepository.findById(organizationId);
	}

	public void saveOrg(Organization org) {
		org.setId(UUID.randomUUID().toString());

		orgRepository.save(org);

	}

	public void updateOrg(Organization org) {
		orgRepository.save(org);
	}

	public void deleteOrg(Organization org) {
		orgRepository.deleteById(org.getId());
	}
}

OrganizationServiceController.java

package com.example.organization.controllers;

import com.example.organization.model.Organization;
import com.example.organization.services.OrganizationService;

import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseStatus;

@RestController
@RequestMapping(value = "organizations")
public class OrganizationServiceController {
	@Autowired
	private OrganizationService orgService;

	@RequestMapping(value = "/{organizationId}", method = RequestMethod.GET)
	public Optional<Organization> getOrganization(@PathVariable("organizationId") String organizationId) {
		return orgService.getOrg(organizationId);
	}

	@RequestMapping(value = "/{organizationId}", method = RequestMethod.PUT)
	public void updateOrganization(@PathVariable("organizationId") String orgId, @RequestBody Organization org) {
		orgService.updateOrg(org);
	}

	@RequestMapping(value = "/{organizationId}", method = RequestMethod.POST)
	public void saveOrganization(@RequestBody Organization org) {
		orgService.saveOrg(org);
	}

	@RequestMapping(value = "/{organizationId}", method = RequestMethod.DELETE)
	@ResponseStatus(HttpStatus.NO_CONTENT)
	public void deleteOrganization(@PathVariable("orgId") String orgId, @RequestBody Organization org) {
		orgService.deleteOrg(org);
	}
}

启动服务,访问http://localhost:8761/,查看注册服务,如下图所示:

访问http://localhost:8761/eureka/apps/organizationservice,查看注册服务,如下图所示:

3 通过Eureka查找服务

我们还可以让许可证服务调用该组织服务,而不必直接知晓任何组织服务的位置。许可证服务将通过Eureka来查找组织服务的实际位置。 我们将研究3个不同的Spring/Netflix客户端库,服务消费者可以使用它们来和Ribbon进行交互。    

  • Spring DiscoveryClient;    
  • 启用了RestTemplate的Spring DiscoveryClient;    
  • Netflix Feign客户端。

首先,修改 src/main/java/com/example/licenses/controllers/LicenseServiceController.java以包含许可证服务的新路由。这个新路由允许指定要用于调用服务的客户端的类型。

    @RequestMapping(value="/{licenseId}/{clientType}",method = RequestMethod.GET)
    public License getLicensesWithClient( @PathVariable("organizationId") String organizationId,
                                          @PathVariable("licenseId") String licenseId,
                                          @PathVariable("clientType") String clientType) {

        return licenseService.getLicense(organizationId,licenseId, clientType);
    }

src/main/java/com/thoughtmechanix/licenses/services/LicenseService.java中的LicenseService类添加了一个名为retrieveOrgInfo()的简单方法,该方法将根据传递到路由的clientType类型进行解析,以用于查找组织服务实例。LicenseService类上的getLicense()方法将使用retrieveOrgInfo()方法从Postgres数据库中检索组织数据。

    public License getLicense(String organizationId,String licenseId, String clientType) {
        License license = licenseRepository.findByOrganizationIdAndLicenseId(organizationId, licenseId);

        Organization org = retrieveOrgInfo(organizationId, clientType);
        return license
                .withOrganizationName( org.getName())
                .withContactName( org.getContactName())
                .withContactEmail( org.getContactEmail() )
                .withContactPhone( org.getContactPhone() )
                .withComment(config.getExampleProperty());
    }
  • 使用Spring DiscoveryClient查找服务实例

要开始使用DiscoveryClient,需要先使用@EnableDiscoveryClient注解来标注src/main/java/com/example/licenses/Application.java中的Application类。

License.java

package com.example.licenses.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;

@Entity
@Table(name = "licenses")
public class License{
  @Id
  @Column(name = "license_id", nullable = false)
  private String licenseId;

  @Column(name = "organization_id", nullable = false)
  private String organizationId;

  @Transient
  private String organizationName ="";

  @Transient
  private String contactName ="";

  @Transient
  private String contactPhone ="";

  @Transient
  private String contactEmail ="";

  @Column(name = "product_name", nullable = false)
  private String productName;

  @Column(name = "license_type", nullable = false)
  private String licenseType;

  @Column(name = "license_max", nullable = false)
  private Integer licenseMax;

  @Column(name = "license_allocated", nullable = false)
  private Integer licenseAllocated;

  @Column(name="comment")
  private String comment;


  public Integer getLicenseMax() {
    return licenseMax;
  }

  public void setLicenseMax(Integer licenseMax) {
    this.licenseMax = licenseMax;
  }

  public Integer getLicenseAllocated() {
    return licenseAllocated;
  }

  public void setLicenseAllocated(Integer licenseAllocated) {
    this.licenseAllocated = licenseAllocated;
  }


  public String getLicenseId() {
    return licenseId;
  }

  public void setLicenseId(String licenseId) {
    this.licenseId = licenseId;
  }

  public String getOrganizationId() {
    return organizationId;
  }

  public void setOrganizationId(String organizationId) {
    this.organizationId = organizationId;
  }

  public String getProductName() {
    return productName;
  }

  public void setProductName(String productName) {
    this.productName = productName;
  }

  public String getLicenseType() {
    return licenseType;
  }

  public void setLicenseType(String licenseType) {
    this.licenseType = licenseType;
  }

  public String getComment() {
    return comment;
  }

  public void setComment(String comment) {
    this.comment = comment;
  }

  public String getOrganizationName() {
    return organizationName;
  }

  public void setOrganizationName(String organizationName) {
    this.organizationName = organizationName;
  }

  public String getContactName() {
    return contactName;
  }

  public void setContactName(String contactName) {
    this.contactName = contactName;
  }

  public String getContactPhone() {
    return contactPhone;
  }

  public void setContactPhone(String contactPhone) {
    this.contactPhone = contactPhone;
  }

  public String getContactEmail() {
    return contactEmail;
  }

  public void setContactEmail(String contactEmail) {
    this.contactEmail = contactEmail;
  }

  public License withId(String id){
    this.setLicenseId(id);
    return this;
  }

  public License withOrganizationId(String organizationId){
    this.setOrganizationId(organizationId);
    return this;
  }

  public License withProductName(String productName){
    this.setProductName(productName);
    return this;
  }

  public License withLicenseType(String licenseType){
    this.setLicenseType(licenseType);
    return this;
  }

  public License withLicenseMax(Integer licenseMax){
    this.setLicenseMax(licenseMax);
    return this;
  }

  public License withLicenseAllocated(Integer licenseAllocated){
    this.setLicenseAllocated(licenseAllocated);
    return this;
  }

  public License withComment(String comment){
    this.setComment(comment);
    return this;
  }

  public License withOrganizationName(String organizationName){
    this.setOrganizationName(organizationName);
    return this;
  }

  public License withContactName(String contactName){
    this.setContactName(contactName);
    return this;
  }

  public License withContactPhone(String contactPhone){
    this.setContactPhone(contactPhone);
    return this;
  }

  public License withContactEmail(String contactEmail){
    this.setContactEmail(contactEmail);
    return this;
  }




}

LicenseService.java

package com.example.licenses.services;

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

import com.example.licenses.clients.OrganizationDiscoveryClient;
import com.example.licenses.config.ServiceConfig;
import com.example.licenses.model.License;
import com.example.licenses.model.Organization;
import com.example.licenses.repository.LicenseRepository;

import java.util.List;
import java.util.UUID;

@Service
public class LicenseService {

	@Autowired
	private LicenseRepository licenseRepository;
  
    @Autowired
    OrganizationDiscoveryClient organizationDiscoveryClient;
    
	@Autowired
	ServiceConfig config;

	public License getLicense(String organizationId, String licenseId) {
		License license = licenseRepository.findByOrganizationIdAndLicenseId(organizationId, licenseId);
		if (license != null) {
			license.withComment(config.getExampleProperty());
		}
		return license;
	}

	public List<License> getLicensesByOrg(String organizationId) {
		return licenseRepository.findByOrganizationId(organizationId);
	}

	public void saveLicense(License license) {
		license.withId(UUID.randomUUID().toString());

		licenseRepository.save(license);

	}

	public void updateLicense(License license) {
		licenseRepository.save(license);
	}

	public void deleteLicense(String licenseId) {
		licenseRepository.deleteById(licenseId);
	}
	
    public License getLicense(String organizationId,String licenseId, String clientType) {
        License license = licenseRepository.findByOrganizationIdAndLicenseId(organizationId, licenseId);

        Organization org = retrieveOrgInfo(organizationId, clientType);
        return license
                .withOrganizationName( org.getName())
                .withContactName( org.getContactName())
                .withContactEmail( org.getContactEmail() )
                .withContactPhone( org.getContactPhone() )
                .withComment(config.getExampleProperty());
    }
    
    private Organization retrieveOrgInfo(String organizationId, String clientType){
        Organization organization = null;

        switch (clientType) {
            case "discovery":
                System.out.println("I am using the discovery client");
                organization = organizationDiscoveryClient.getOrganization(organizationId);
                break;
        }

        return organization;
    }


}

LicenseServiceController.java

package com.example.licenses.controllers;

import com.example.licenses.model.License;
import com.example.licenses.services.LicenseService;
import com.example.licenses.config.ServiceConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.util.List;

@RestController
@RequestMapping(value = "organizations/{organizationId}/licenses")
public class LicenseServiceController {
	@Autowired
	private LicenseService licenseService;

	@Autowired
	private ServiceConfig serviceConfig;

	/**
	 * 查询所有对象
	 * 
	 * @param organizationId
	 * @return
	 */
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public List<License> getLicenses(@PathVariable("organizationId") String organizationId) {

		return licenseService.getLicensesByOrg(organizationId);
	}

	/**
	 * 查询单个对象
	 * 
	 * @param organizationId
	 * @param licenseId
	 * @return
	 */
	@RequestMapping(value = "/{licenseId}", method = RequestMethod.GET)
	public License getLicenses(@PathVariable("organizationId") String organizationId,
			@PathVariable("licenseId") String licenseId) {

		return licenseService.getLicense(organizationId, licenseId);
	}

	/**
	 * 新增对象
	 * 
	 * @param license
	 */
	@RequestMapping(value = "/", method = RequestMethod.POST)
	public void saveLicenses(@RequestBody License license) {
		licenseService.saveLicense(license);
	}

	/**
	 * 更新对象
	 * 
	 * @param licenseId
	 * @return
	 */
	@RequestMapping(value = "/", method = RequestMethod.PUT)
	public String updateLicenses(@RequestBody License license) {
		licenseService.updateLicense(license);
		return String.format("This is the put");
	}

	/**
	 * 删除对象
	 * 
	 * @param licenseId
	 * @return
	 */
	@RequestMapping(value = "{licenseId}", method = RequestMethod.DELETE)
	// @ResponseStatus(HttpStatus.NO_CONTENT)
	public String deleteLicenses(@PathVariable("licenseId") String licenseId) {
		licenseService.deleteLicense(licenseId);
		return String.format("This is the Delete");
	}
	
    @RequestMapping(value="/{licenseId}/{clientType}",method = RequestMethod.GET)
    public License getLicensesWithClient( @PathVariable("organizationId") String organizationId,
                                          @PathVariable("licenseId") String licenseId,
                                          @PathVariable("clientType") String clientType) {
        return licenseService.getLicense(organizationId,licenseId, clientType);
    }

}

OrganizationDiscoveryClient.java

package com.example.licenses.clients;

import com.example.licenses.model.Organization;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@Component
public class OrganizationDiscoveryClient {

	@Autowired
	private DiscoveryClient discoveryClient;

	public Organization getOrganization(String organizationId) {
		RestTemplate restTemplate = new RestTemplate();
		List<ServiceInstance> instances = discoveryClient.getInstances("organizationservice");

		if (instances.size() == 0)
			return null;
		String serviceUri = String.format("%s/organizations/%s", instances.get(0).getUri().toString(), organizationId);
		System.out.println("!!!! SERVICE URI:  " + serviceUri);

		ResponseEntity<Organization> restExchange = restTemplate.exchange(serviceUri, HttpMethod.GET, null,
				Organization.class, organizationId);

		return restExchange.getBody();
	}
}

启动服务,访问http://localhost:8080/organizations/442adb6e-fa58-47f3-9ca2-ed1fecdfe86c/licenses/08dbe05-606e-4dad-9d33-90ef10e334f9/discovery,查询许可证信息,如下图所示:

  • 使用带有Ribbon功能的Spring RestTemplate调用服务

要使用带有Ribbon功能的Spring RestTemplate类,需要使用Spring Cloud注解@LoadBalanced来定义RestTemplate的构造方法。对于许可证服务,可以在src/main/java/com/example/licenses/LicensingServiceApplication.java中找到用于创建RestTemplate bean的方法。

LicenseService.java

package com.example.licenses.services;

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

import com.example.licenses.clients.OrganizationDiscoveryClient;
import com.example.licenses.clients.OrganizationFeignClient;
import com.example.licenses.clients.OrganizationRestTemplateClient;
import com.example.licenses.config.ServiceConfig;
import com.example.licenses.model.License;
import com.example.licenses.model.Organization;
import com.example.licenses.repository.LicenseRepository;

import java.util.List;
import java.util.UUID;

@Service
public class LicenseService {

	@Autowired
	private LicenseRepository licenseRepository;

	@Autowired
	ServiceConfig config;
	
    @Autowired
    OrganizationDiscoveryClient organizationDiscoveryClient;
    
    @Autowired
    OrganizationRestTemplateClient organizationRestClient;

    @Autowired
    OrganizationFeignClient organizationFeignClient;
    
	public License getLicense(String organizationId, String licenseId) {
		License license = licenseRepository.findByOrganizationIdAndLicenseId(organizationId, licenseId);
		if (license != null) {
			license.withComment(config.getExampleProperty());
		}
		return license;
	}
	
    public License getLicense(String organizationId,String licenseId, String clientType) {
        License license = licenseRepository.findByOrganizationIdAndLicenseId(organizationId, licenseId);

        Organization org = retrieveOrgInfo(organizationId, clientType);

        return license
                .withOrganizationName( org.getName())
                .withContactName( org.getContactName())
                .withContactEmail( org.getContactEmail() )
                .withContactPhone( org.getContactPhone() )
                .withComment(config.getExampleProperty());
    }
    
    private Organization retrieveOrgInfo(String organizationId, String clientType){
        Organization organization = null;

        switch (clientType) {
            case "discovery":
                System.out.println("I am using the discovery client");
                organization = organizationDiscoveryClient.getOrganization(organizationId);
                break;
            case "rest":
                System.out.println("I am using the rest client");
                organization = organizationRestClient.getOrganization(organizationId);
                break;
            case "feign":
                System.out.println("I am using the feign client");
                organization = organizationFeignClient.getOrganization(organizationId);
                break;
        }

        return organization;
    }

	public List<License> getLicensesByOrg(String organizationId) {
		return licenseRepository.findByOrganizationId(organizationId);
	}

	public void saveLicense(License license) {
		license.withId(UUID.randomUUID().toString());

		licenseRepository.save(license);

	}

	public void updateLicense(License license) {
		licenseRepository.save(license);
	}

	public void deleteLicense(String licenseId) {
		licenseRepository.deleteById(licenseId);
	}

}

LicensingServiceApplication.java

package com.example.licenses;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
import java.util.Collections;
import java.util.List;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class LicensingServiceApplication {

	@LoadBalanced
	@Bean
	public RestTemplate getRestTemplate() {
		return new RestTemplate();
	}

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

OrganizationRestTemplateClient.java

package com.example.licenses.clients;

import com.example.licenses.model.Organization;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@Component
public class OrganizationRestTemplateClient {
    @Autowired
    RestTemplate restTemplate;

    public Organization getOrganization(String organizationId){
        ResponseEntity<Organization> restExchange =
                restTemplate.exchange(
                        "http://organizationservice/organizations/{organizationId}",
                        HttpMethod.GET,
                        null, Organization.class, organizationId);

        return restExchange.getBody();
    }
}

启动服务,访问http://localhost:8080/organizations/442adb6e-fa58-47f3-9ca2-ed1fecdfe86c/licenses/08dbe05-606e-4dad-9d33-90ef10e334f9/rest,查询许可证信息,如下图所示:

  • 使用Netflix Feign客户端调用服务

要在许可证服务中允许使用Feign客户端,需要向许可证服务的src/main/java/com/example/licenses/LicensingServiceApplication.java添加一个新注解@EnableFeignClients。

在pom.xml中增加以下依赖jar包:

    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>

OrganizationFeignClient.java

package com.example.licenses.clients;

import com.example.licenses.model.Organization;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@FeignClient("organizationservice")
public interface OrganizationFeignClient {
	@RequestMapping(method = RequestMethod.GET, value = "organizations/{organizationId}", consumes = "application/json")
	Organization getOrganization(@PathVariable("organizationId") String organizationId);
}

启动服务,访问http://localhost:8080/organizations/442adb6e-fa58-47f3-9ca2-ed1fecdfe86c/licenses/08dbe05-606e-4dad-9d33-90ef10e334f9/feign,查询许可证信息,如下图所示:

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