使用Spring Boot的微服务。 第3部分。创建货币转换微服务

这是有关微服务体系结构基础的系列文章的第三部分,您将在其中学习如何创建用于货币换算的微服务。

在本系列文章中,您将熟悉微服务的概念,并学习如何使用Spring Boot和Spring Cloud创建微服务。

本指南将帮助您学习微服务架构的基础。 我们还将开始研究Spring Boot的基本微服务实现。

我们将创建一对微服务,并使它们使用Eureka(Eureka命名服务器)和Ribbon名称服务器相互通信,以平衡客户端的负载。

本文是“带Spring Boot的微服务”系列文章的一部分:


你会学


  • 如何使用Spring Boot创建微服务
  • 如何使用RestTemplate创建REST服务。
  • 如何使用Feign创建REST服务。
  • 假装胜过RestTemplate的好处。

资源总览


货币转换服务(CCS)可以将许多货币转换为另一种货币。 它使用外汇服务来获取当前货币兑换值。 CCS是服务的消费者。

请求和响应的示例如下所示:

GET to http://localhost:8100/currency-converter/from/EUR/to/INR/quantity/10000 

 { id: 10002, from: "EUR", to: "INR", conversionMultiple: 75, quantity: 10000, totalCalculatedAmount: 750000, port: 8000, } 

上面的请求使您可以确定10,000欧元的印度卢比价值。
TotalCalculatedAmount为750,000 INR。 下图显示了CCS和FS之间的关系。



项目代码结构


以下屏幕快照显示了我们将创建的项目的结构。



项目的一些要素:

  • SpringBootMicroserviceCurrencyConversionApplication.java是使用Spring Initializer创建的Spring Boot应用程序类。 此类充当应用程序启动点。
  • pom.xml-包含创建此项目所需的所有依赖项。 我们将使用Spring Boot Starter Web。
  • CurrencyConversionBean.java-存储我们要发送的响应的bean。
  • CurrencyExchangeServiceProxy.java-这将是用于调用外汇服务的伪装代理。
  • CurrencyConversionController.java-提供货币转换服务的Spring REST控制器。 它将使用CurrencyExchangeServiceProxy调用外汇服务。

您需要的工具


  • Maven 3.0+-构建工具
  • 您最喜欢的IDE。 我们使用Eclipse。
  • JDK 1.8以上

带有代码示例的Ready Maven项目


Github存储库包含所有代码示例。

使用Spring Initializr创建一个项目


使用Spring Initializr创建微服务很容易。

Spring Initializr是用于快速创建Spring Boot项目的出色工具。

借助Spring Initializr,您可以创建各种项目。



必须采取以下步骤来创建Web服务开发项目:

1.启动Spring Initializr并输入以下内容:

  • 分组输入com.in28minutes.springboot.microservice.example.currencyconversion
  • 键入spring-boot-microservice-currency-conversion作为工件。
  • 选择以下依赖项: WebDevToolsFeign

2.单击生成项目

3.将项目导入Eclipse:File-> Import-> Existing Maven Project。

请记住在依赖中列出Feign

创建CurrencyConversionBean


这是一个创建答案的简单bean。

 public class CurrencyConversionBean { private Long id; private String from; private String to; private BigDecimal conversionMultiple; private BigDecimal quantity; private BigDecimal totalCalculatedAmount; private int port; public CurrencyConversionBean() { } public CurrencyConversionBean(Long id, String from, String to, BigDecimal conversionMultiple, BigDecimal quantity, BigDecimal totalCalculatedAmount, int port) { super(); this.id = id; this.from = from; this.to = to; this.conversionMultiple = conversionMultiple; this.quantity = quantity; this.totalCalculatedAmount = totalCalculatedAmount; this.port = port; } 

使用RestTemplate实现REST客户端


下面的代码演示了用于调用Forex服务并处理响应的REST客户端的实现。 如您所见,要进行简单的服务调用,您需要编写大量代码。

 @RestController public class CurrencyConversionController { private Logger logger = LoggerFactory.getLogger(this.getClass()); @GetMapping("/currency-converter/from/{from}/to/{to}/quantity/{quantity}") public CurrencyConversionBean convertCurrency(@PathVariable String from, @PathVariable String to, @PathVariable BigDecimal quantity) { Map<String, String> uriVariables = new HashMap<>(); uriVariables.put("from", from); uriVariables.put("to", to); ResponseEntity<CurrencyConversionBean> responseEntity = new RestTemplate().getForEntity( "http://localhost:8000/currency-exchange/from/{from}/to/{to}", CurrencyConversionBean.class, uriVariables); CurrencyConversionBean response = responseEntity.getBody(); return new CurrencyConversionBean(response.getId(), from, to, response.getConversionMultiple(), quantity, quantity.multiply(response.getConversionMultiple()), response.getPort()); } 

配置应用程序名称和端口


/spring-boot-microservice-currency-conversion-service/src/main/resources/application.properties

 spring.application.name=currency-conversion-service server.port=8100 

微服务测试


通过运行SpringBootMicroserviceCurrencyConversionApplication.java启动Spring Boot应用程序

 GET to http://localhost:8100/currency-converter/from/EUR/to/INR/quantity/10000 

 { id: 10002, from: "EUR", to: "INR", conversionMultiple: 75, quantity: 10000, totalCalculatedAmount: 750000, port: 8000, } 

创建假代理


Feign提供了RestTemplate的最佳替代方法来调用REST API。

/spring-boot-microservice-currency-conversion-service/src/main/java/com/in28minutes/springboot/microservice/example/currencyconversion/CurrencyExchangeServiceProxy.java

 package com.in28minutes.springboot.microservice.example.currencyconversion; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.cloud.netflix.ribbon.RibbonClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @FeignClient(name="forex-service" url="localhost:8000") public interface CurrencyExchangeServiceProxy { @GetMapping("/currency-exchange/from/{from}/to/{to}") public CurrencyConversionBean retrieveExchangeValue (@PathVariable("from") String from, @PathVariable("to") String to); } 

首先,我们定义一个简单的代理:

  • @FeignClient(名称=“ forex-service” url =“ localhost:8100”) -声明这是一个Feign客户端,外汇服务所在的URL为localhost:8100
  • @GetMapping(“ / currency-exchange / from / {from} /到/ {to}”) -我们要使用的服务的URI

在微服务控制器中使用伪装代理


通过代理进行呼叫非常简单。 您将在下面的代码中看到此操作。 我们要做的就是自动连接代理并使用它来调用方法。

 @Autowired private CurrencyExchangeServiceProxy proxy; @GetMapping("/currency-converter-feign/from/{from}/to/{to}/quantity/{quantity}") public CurrencyConversionBean convertCurrencyFeign(@PathVariable String from, @PathVariable String to, @PathVariable BigDecimal quantity) { CurrencyConversionBean response = proxy.retrieveExchangeValue(from, to); logger.info("{}", response); return new CurrencyConversionBean(response.getId(), from, to, response.getConversionMultiple(), quantity, quantity.multiply(response.getConversionMultiple()), response.getPort()); } 

支持假客户


在使用Feign之前,我们需要在定义客户端代理的相应程序包中使用@EnableFeignClients批注启用它。

 @SpringBootApplication @EnableFeignClients("com.in28minutes.springboot.microservice.example.currencyconversion") @EnableDiscoveryClient public class SpringBootMicroserviceCurrencyConversionApplication { public static void main(String[] args) { SpringApplication.run(SpringBootMicroserviceCurrencyConversionApplication.class, args); } } 

使用Feign测试微服务


 GET to http://localhost:8100/currency-converter-feign/from/EUR/to/INR/quantity/10000 


 { id: 10002, from: "EUR", to: "INR", conversionMultiple: 75, quantity: 10000, totalCalculatedAmount: 750000, port: 8000, } 

总结


我们创建了两个微服务,并在它们之间建立了连接。



但是,我们将FS的URL硬编码为CCS。 这意味着,当启动新的FS实例时,我们无法在它们之间分配负载。 在下一部分中,我们将使用功能区启用客户端负载平衡。

完整的示例代码

/spring-boot-microservice-currency-conversion-service/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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.in28minutes.springboot.microservice.example.currency-conversion</groupId> <artifactId>spring-boot-microservice-currency-conversion</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>spring-boot-microservice-currency-conversion</name> <description>Microservices with Spring Boot and Spring Cloud - Currency Conversion Service</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.M3</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Finchley.M2</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <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> <repositories> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <snapshots> <enabled>true</enabled> </snapshots> </repository> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <snapshots> <enabled>true</enabled> </snapshots> </pluginRepository> <pluginRepository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> </pluginRepositories> </project> 

/spring-boot-microservice-currency-conversion-service/src/main/java/com/in28minutes/springboot/microservice/example/currencyconversion/CurrencyConversionBean.java


 package com.in28minutes.springboot.microservice.example.currencyconversion; import java.math.BigDecimal; public class CurrencyConversionBean { private Long id; private String from; private String to; private BigDecimal conversionMultiple; private BigDecimal quantity; private BigDecimal totalCalculatedAmount; private int port; public CurrencyConversionBean() { } public CurrencyConversionBean(Long id, String from, String to, BigDecimal conversionMultiple, BigDecimal quantity, BigDecimal totalCalculatedAmount, int port) { super(); this.id = id; this.from = from; this.to = to; this.conversionMultiple = conversionMultiple; this.quantity = quantity; this.totalCalculatedAmount = totalCalculatedAmount; this.port = port; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getFrom() { return from; } public void setFrom(String from) { this.from = from; } public String getTo() { return to; } public void setTo(String to) { this.to = to; } public BigDecimal getConversionMultiple() { return conversionMultiple; } public void setConversionMultiple(BigDecimal conversionMultiple) { this.conversionMultiple = conversionMultiple; } public BigDecimal getQuantity() { return quantity; } public void setQuantity(BigDecimal quantity) { this.quantity = quantity; } public BigDecimal getTotalCalculatedAmount() { return totalCalculatedAmount; } public void setTotalCalculatedAmount(BigDecimal totalCalculatedAmount) { this.totalCalculatedAmount = totalCalculatedAmount; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } } 

/spring-boot-microservice-currency-conversion-service/src/main/java/com/in28minutes/springboot/microservice/example/currencyconversion/CurrencyConversionController.java


 package com.in28minutes.springboot.microservice.example.currencyconversion; import java.math.BigDecimal; import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController public class CurrencyConversionController { private Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired private CurrencyExchangeServiceProxy proxy; @GetMapping("/currency-converter/from/{from}/to/{to}/quantity/{quantity}") public CurrencyConversionBean convertCurrency(@PathVariable String from, @PathVariable String to, @PathVariable BigDecimal quantity) { Map<String, String> uriVariables = new HashMap<>(); uriVariables.put("from", from); uriVariables.put("to", to); ResponseEntity<CurrencyConversionBean> responseEntity = new RestTemplate().getForEntity( "http://localhost:8000/currency-exchange/from/{from}/to/{to}", CurrencyConversionBean.class, uriVariables); CurrencyConversionBean response = responseEntity.getBody(); return new CurrencyConversionBean(response.getId(), from, to, response.getConversionMultiple(), quantity, quantity.multiply(response.getConversionMultiple()), response.getPort()); } @GetMapping("/currency-converter-feign/from/{from}/to/{to}/quantity/{quantity}") public CurrencyConversionBean convertCurrencyFeign(@PathVariable String from, @PathVariable String to, @PathVariable BigDecimal quantity) { CurrencyConversionBean response = proxy.retrieveExchangeValue(from, to); logger.info("{}", response); return new CurrencyConversionBean(response.getId(), from, to, response.getConversionMultiple(), quantity, quantity.multiply(response.getConversionMultiple()), response.getPort()); } } 

/spring-boot-microservice-currency-conversion-service/src/main/java/com/in28minutes/springboot/microservice/example/currencyconversion/CurrencyExchangeServiceProxy.java


 package com.in28minutes.springboot.microservice.example.currencyconversion; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.cloud.netflix.ribbon.RibbonClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @FeignClient(name="forex-service" url="localhost:8000") public interface CurrencyExchangeServiceProxy { @GetMapping("/currency-exchange/from/{from}/to/{to}") public CurrencyConversionBean retrieveExchangeValue (@PathVariable("from") String from, @PathVariable("to") String to); } 

/spring-boot-microservice-currency-conversion-service/src/main/java/com/in28minutes/springboot/microservice/example/currencyconversion/SpringBootMicroserviceCurrencyConversionApplication.java


 package com.in28minutes.springboot.microservice.example.currencyconversion; 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 @EnableFeignClients("com.in28minutes.springboot.microservice.example.currencyconversion") public class SpringBootMicroserviceCurrencyConversionApplication { public static void main(String[] args) { SpringApplication.run(SpringBootMicroserviceCurrencyConversionApplication.class, args); } } 

/spring-boot-microservice-currency-conversion-service/src/main/resources/application.properties


 spring.application.name=currency-conversion-service server.port=8100 

/spring-boot-microservice-currency-conversion-service/src/test/java/com/in28minutes/springboot/microservice/example/currencyconversion/SpringBootMicroserviceCurrencyConversionApplicationTests.java


 package com.in28minutes.springboot.microservice.example.currencyconversion; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class SpringBootMicroserviceCurrencyConversionApplicationTests { @Test public void contextLoads() { } } 

Source: https://habr.com/ru/post/zh-CN485094/


All Articles