Il s'agit de la troisième partie d'une série d'articles sur les bases des architectures de microservices, dans laquelle vous apprendrez à créer un microservice pour la conversion de devises.
Dans cette série d'articles, vous vous familiariserez avec le concept des microservices et apprendrez à créer des microservices à l'aide de Spring Boot et Spring Cloud.
Ce guide vous aidera à apprendre les bases des architectures de microservices. Nous allons également commencer à examiner l'implémentation de base des microservices avec Spring Boot.
Nous allons créer une paire de microservices et les faire communiquer entre eux à l'aide des serveurs de noms Eureka (Eureka Naming Server) et Ribbon pour équilibrer la charge côté client.
Cet article fait partie de la série Spring Boot Microservices:
Vous apprendrez
- Comment créer un microservice à l'aide de Spring Boot.
- Comment utiliser RestTemplate pour créer un service REST.
- Comment utiliser Feign pour créer un service REST.
- Avantages de Feign sur RestTemplate.
Présentation des ressources
Le service de conversion de devises (CCS) peut convertir de nombreuses devises dans une autre devise. Il utilise le service Forex pour obtenir les valeurs de change actuelles. CCS est un consommateur de services.
Un exemple de demande et de réponse est présenté ci-dessous:
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, }
La demande ci-dessus vous permet de déterminer la valeur de 10 000 euros en roupies indiennes.
Le montant total calculé est de 750 000 INR. Le diagramme ci-dessous montre la relation entre CCS et FS.

Structure du code de projet
La capture d'écran suivante montre la structure du projet que nous allons créer.

Quelques éléments du projet:
- SpringBootMicroserviceCurrencyConversionApplication.java est la classe d'application Spring Boot créée à l'aide de Spring Initializer. Cette classe sert de point de lancement d'application.
- pom.xml - contient toutes les dépendances nécessaires pour créer ce projet. Nous utiliserons le Spring Boot Starter Web.
- CurrencyConversionBean.java - Le bean pour stocker la réponse que nous voulons envoyer.
- CurrencyExchangeServiceProxy.java - ce sera le proxy Feign pour appeler le service Forex.
- CurrencyConversionController.java - Contrôleur Spring REST qui fournit un service de conversion de devises. Il utilisera CurrencyExchangeServiceProxy pour appeler le service Forex.
Outils dont vous avez besoin
- Maven 3.0+ - outil de construction
- Votre IDE préféré. Nous utilisons Eclipse.
- JDK 1.8+
Projet Ready Maven avec des échantillons de code
Le référentiel Github contient tous les exemples de code.
Création d'un projet à l'aide de Spring Initializr
La création d'un microservice avec Spring Initializr est une marche facile.
Spring Initializr est un excellent outil pour créer rapidement vos projets Spring Boot.
Avec l'aide de
Spring Initializr, vous pouvez créer une variété de projets.

Les étapes suivantes doivent être suivies pour créer un projet de développement de services Web:
1. Lancez Spring Initializr et tapez ce qui suit:
- Tapez com.in28minutes.springboot.microservice.example.currencyconversion en tant que groupe.
- Tapez spring-boot-microservice-currency-conversion comme un artefact.
- Sélectionnez les dépendances suivantes: Web , DevTools , Feign
2. Cliquez sur
Générer un projet .
3. Importez le projet dans Eclipse: Fichier -> Importer -> Projet Maven existant.
N'oubliez pas de lister
Feign dans les dépendances.
Création de CurrencyConversionBean
Il s'agit d'un simple bean pour créer une réponse.
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; }
Implémentation d'un client REST avec RestTemplate
Le code ci-dessous illustre l'implémentation d'un client REST pour appeler un service Forex et traiter une réponse. Comme vous pouvez le voir, pour effectuer un appel de service simple, vous devez écrire beaucoup de code.
@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()); }
Configurer le nom et le port de l'application
/spring-boot-microservice-currency-conversion-service/src/main/resources/application.properties spring.application.name=currency-conversion-service server.port=8100
Test de microservices
Lancez l'application Spring Boot en exécutant SpringBootMicroserviceCurrencyConversionApplication.java
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, }
Création de proxys feints
Feign fournit la meilleure alternative à RestTemplate pour appeler l'API REST.
/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); }
Nous définissons d'abord un proxy simple:
- @FeignClient (name = "forex-service" url = "localhost: 8100") - déclare qu'il s'agit d'un client Feign et que l'URL où se trouve le service Forex est localhost: 8100
- @GetMapping ("/ currency-exchange / from / {from} / to / {to}") - L'URI du service que nous aimerions utiliser
Utilisation de proxys Feign dans un contrôleur de microservice
Passer un appel via un proxy est très simple. Vous le verrez en action dans le code ci-dessous. Tout ce que nous avions à faire était de connecter automatiquement le proxy et de l'utiliser pour appeler la méthode.
@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()); }
Activation des clients Feign
Avant de pouvoir utiliser Feign, nous devons l'activer à l'aide de l'annotation @EnableFeignClients dans le package approprié où les proxys clients sont définis.
@SpringBootApplication @EnableFeignClients("com.in28minutes.springboot.microservice.example.currencyconversion") @EnableDiscoveryClient public class SpringBootMicroserviceCurrencyConversionApplication { public static void main(String[] args) { SpringApplication.run(SpringBootMicroserviceCurrencyConversionApplication.class, args); } }
Test d'un microservice à l'aide de 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, }
Résumé
Nous avons créé deux microservices et établi une connexion entre eux.

Cependant, nous avons codé en dur l'URL de FS vers CCS. Cela signifie que lorsque de nouvelles instances FS sont lancées, nous n'avons aucun moyen de répartir la charge entre elles. Dans la partie suivante, nous activerons l'équilibrage de charge côté client à l'aide du ruban.
Exemple de code complet/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 /> </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() { } }