Pull to refresh

Микросервисы со Spring Boot. Часть 2. Создание микросервиса Forex

Reading time11 min
Views22K
Original author: Ranga Karanam
Это вторая часть серии статей по основам микросервисных архитектур, в которой показывается, как создать микросервис с помощью Spring Boot и заставить его работать с Spring MVC, JPA, Hibernate и H2.

В этой серии статей вы познакомитесь с концепцией микросервисов и узнаете, как создавать микросервисы с помощью Spring Boot и Spring Cloud.

Это руководство поможет вам изучить основы микросервисных архитектур. Мы также начнем рассматривать базовую реализацию микросервиса со Spring Boot.

Мы создадим пару микросервисов и заставим их общаться друг с другом с помощью сервера имен Eureka (Eureka Naming Server) и Ribbon для балансировки нагрузки на стороне клиента.

Это статья входит в серию статей «Микросервисы со Spring Boot»:


Вы изучите


  • Как создать микросервис с помощью Spring Boot?
  • Как создать JPA сущность и ресурс?
  • Как заставить Spring MVC, Spring Boot, JPA, Hibernate и H2 работать вместе?

Обзор ресурсов


Forex Service (FS) является поставщиком услуг. Он обеспечивает значения курсов обмена валюты для различных валют. Давайте предположим, что он общается с Forex Exchange и предоставляет текущие значения курсов обмена различных валют.

Пример запроса и ответа показан ниже:

GET to http://localhost:8000/currency-exchange/from/EUR/to/INR

{
  id: 10002,
  from: "EUR",
  to: "INR",
  conversionMultiple: 75,
  port: 8000,
}

Запрос выше возвращает обменный курс евро к INR. В ответе получается, что коэффициент конвертации ConversionMultiple равен 75.

Структура кода проекта


На следующем скриншоте показана структура проекта, который мы создадим.



Некоторые элементы проекта:

  • SpringBootMicroserviceForexServiceApplication.java — класс Spring Boot приложения, созданный с помощью Spring Initializer. Этот класс действует как точка запуска приложения.
  • pom.xml — содержит все зависимости, необходимые для создания этого проекта. Мы будем использовать Spring Boot Starter Web и JPA.
  • ExchangeValue.java — объект, содержащий количество валюты для обмена.
  • ExchangeValueRepository.java — JPA репозиторий для ExchangeValue. Он создан с помощью Spring Data JpaRepository.
  • ForexController.java — Spring REST контроллер, предоставляющий сервис конвертации форекс.
  • data.sql — исходные данные для таблицы exchange_value. Spring Boot выполнит этот скрипт после того, как таблицы будут созданы из сущностей.

Вам понадобятся


  • Maven 3.0+ — инструмент для сборки
  • Ваш любимый IDE. Мы используем Eclipse.
  • JDK 1.8+

Готовый проект Maven с примерами кода


В Github репозитории есть все примеры кода.

Создание проекта с помощью Spring Initializr


Создание микросервиса с Spring Initializr — это легкая прогулка.

Spring Initializr: start.spring.io — отличный инструмент для быстрого создания ваших проектов Spring Boot.

С помощью Spring Initializr вы можете создавать самые разные проекты.



Следующие шаги нужно сделать для создания проекта разработки веб-сервисов:

1. Запустите Spring Initializr и наберите следующее:

  • Наберите com.in28minutes.springboot.microservice.example.forex в качестве группы.
  • Наберите в качестве артефакта spring-boot-microservice-forex-service.
  • Выберите следующие зависимости:

— Web
— DevTools
— Стартер JPA
— H2

2. Нажмите Generate Project.

3. Импортируйте проект в Eclipse: File -> Import -> Existing Maven Project.

Создание класса Exchange Value


@Entity
public class ExchangeValue {
  
  @Id
  private Long id;
  
  @Column(name="currency_from")
  private String from;
  
  @Column(name="currency_to")
  private String to;
  
  private BigDecimal conversionMultiple;
  private int port;
  
  public ExchangeValue() {
    
  }
  

  public ExchangeValue(Long id, String from, String to, BigDecimal conversionMultiple) {
    super();
    this.id = id;
    this.from = from;
    this.to = to;
    this.conversionMultiple = conversionMultiple;
  }

  public Long getId() {
    return id;
  }

  public String getFrom() {
    return from;
  }

  public String getTo() {
    return to;
  }

  public BigDecimal getConversionMultiple() {
    return conversionMultiple;
  }
  
  public int getPort() {
    return port;
  }

  public void setPort(int port) {
    this.port = port;
  }

}

Важные вещи, на которые стоит обратить внимание:

  • Entity: указывает, что класс является сущностью. Эта аннотация применяется к классу сущностей.
  • Id: Определяет первичный ключ объекта.

Создание JPA-репозитория Exchange Value


/spring-boot-microservice-forex-service/src/main/java/com/in28minutes/springboot/microservice/example/forex/ExchangeValueRepository.java

package com.in28minutes.springboot.microservice.example.forex;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ExchangeValueRepository extends 
    JpaRepository<ExchangeValue, Long>{
  ExchangeValue findByFromAndTo(String from, String to);
}

Примечания:

1. public interface ExchangeValueRepository extends JpaRepository<ExchangeValue, Long>

расширяет JpaRepository, используя два дженерика: ExchangeValue и Long. ExchangeValue является объектом, которым управляют, а первичным ключом ExchangeValue является Long.

2. ExchangeValue findByFromAndTo (String from, String to)

определяет метод запроса стоимости конвертации из одной валюты в другую.

Создаем ресурс ForexController


/spring-boot-microservice-forex-service/src/main/java/com/in28minutes/springboot/microservice/example/forex/ForexController.java

@RestController
public class ForexController {
  
  @Autowired
  private Environment environment;
  
  @Autowired
  private ExchangeValueRepository repository;
  
  @GetMapping("/currency-exchange/from/{from}/to/{to}")
  public ExchangeValue retrieveExchangeValue
    (@PathVariable String from, @PathVariable String to){
    
    ExchangeValue exchangeValue = 
        repository.findByFromAndTo(from, to);
    
    exchangeValue.setPort(
        Integer.parseInt(environment.getProperty("local.server.port")));
    
    return exchangeValue;
  }
}

Примечания:

1. @RestController public class ForexController {

&nbsp&nbsp&nbsp создает контроллер для предоставления REST сервиса

2. Autowired private Environment environment

&nbsp&nbsp&nbsp возвращает порт (port) сервера. Это поможет определить, какой экземпляр сервиса возвращает ответ.

3. Autowired private ExchangeValueRepository repository — автоматическое подключение репозитория.

4. ExchangeValue exchangeValue = repository.findByFromAndTo(from, to) — получаем значение курса обмена валют из базы данных.

5. exchangeValue.setPort(Integer.parseInt(environment.getProperty(«local.server.port»)))

&nbsp&nbsp&nbsp получает атрибут порт (port) из объекта environment и устанавливает его в бин ответа.

Настройка Application Name и несколько других настроек


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

spring.application.name=forex-service
server.port=8000

spring.jpa.show-sql=true
spring.h2.console.enabled=true

Назначаем порт 8000 для этого приложения и включаем ведение журнала для отладки.

Вставляем некоторые тестовые данные в data.sql


Давайте вставим некоторые тестовые данные, создав файл с именем data.sql. Spring Boot Auto Configuration обеспечивает загрузку этих данных при запуске приложения.

/spring-boot-microservice-forex-service/src/main/resources/data.sql

insert into exchange_value(id,currency_from,currency_to,conversion_multiple,port)
values(10001,'USD','INR',65,0);
insert into exchange_value(id,currency_from,currency_to,conversion_multiple,port)
values(10002,'EUR','INR',75,0);
insert into exchange_value(id,currency_from,currency_to,conversion_multiple,port)
values(10003,'AUD','INR',25,0);

Тестируем Forex микросервис


GET to http://localhost:8000/currency-exchange/from/EUR/to/INR

{
  id: 10002,
  from: "EUR",
  to: "INR",
  conversionMultiple: 75,
  port: 8000,
}

Далее в этой серии статей:


  • Создание сервиса конвертации валют CCS. Мы создадим простой REST сервис, используя Feign для вызова микросервиса Forex.
  • Использование Ribbon для балансировки нагрузки.
  • Внедрение Eureka Naming Service и подключение FS и CCS через Eureka.

Полный код примера

/spring-boot-microservice-forex-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.forex</groupId>
  <artifactId>spring-boot-microservice-forex-service</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>spring-boot-microservice-forex-service</name>
  <description>Microservices with Spring Boot and Spring Cloud - Forex Service</description>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.0.RELEASE</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.M8</spring-cloud.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-devtools</artifactId>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</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-forex-service/src/main/java/com/in28minutes/springboot/microservice/example/forex/ExchangeValue.java


package com.in28minutes.springboot.microservice.example.forex;
import java.math.BigDecimal;

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

@Entity
public class ExchangeValue {
  
  @Id
  private Long id;
  
  @Column(name="currency_from")
  private String from;
  
  @Column(name="currency_to")
  private String to;
  
  private BigDecimal conversionMultiple;
  private int port;
  
  public ExchangeValue() {
    
  }
  

  public ExchangeValue(Long id, String from, String to, BigDecimal conversionMultiple) {
    super();
    this.id = id;
    this.from = from;
    this.to = to;
    this.conversionMultiple = conversionMultiple;
  }

  public Long getId() {
    return id;
  }

  public String getFrom() {
    return from;
  }

  public String getTo() {
    return to;
  }

  public BigDecimal getConversionMultiple() {
    return conversionMultiple;
  }
  
  public int getPort() {
    return port;
  }

  public void setPort(int port) {
    this.port = port;
  }

}

/spring-boot-microservice-forex-service/src/main/java/com/in28minutes/springboot/microservice/example/forex/ExchangeValueRepository.java

package com.in28minutes.springboot.microservice.example.forex;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ExchangeValueRepository extends 
    JpaRepository<ExchangeValue, Long>{
  ExchangeValue findByFromAndTo(String from, String to);
}

/spring-boot-microservice-forex-service/src/main/java/com/in28minutes/springboot/microservice/example/forex/ForexController.java


package com.in28minutes.springboot.microservice.example.forex;
import java.math.BigDecimal;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ForexController {
  
  @Autowired
  private Environment environment;
  
  @Autowired
  private ExchangeValueRepository repository;
  
  @GetMapping("/currency-exchange/from/{from}/to/{to}")
  public ExchangeValue retrieveExchangeValue
    (@PathVariable String from, @PathVariable String to){
    
    ExchangeValue exchangeValue = 
        repository.findByFromAndTo(from, to);
    
    exchangeValue.setPort(
        Integer.parseInt(environment.getProperty("local.server.port")));
    
    return exchangeValue;
  }
}

/spring-boot-microservice-forex-service/src/main/java/com/in28minutes/springboot/microservice/example/forex/SpringBootMicroserviceForexServiceApplication.java


package com.in28minutes.springboot.microservice.example.forex;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootMicroserviceForexServiceApplication {

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

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


spring.application.name=forex-service
server.port=8000

spring.jpa.show-sql=true
spring.h2.console.enabled=true


/spring-boot-microservice-forex-service/src/main/resources/data.sql


insert into exchange_value(id,currency_from,currency_to,conversion_multiple,port)
values(10001,'USD','INR',65,0);
insert into exchange_value(id,currency_from,currency_to,conversion_multiple,port)
values(10002,'EUR','INR',75,0);
insert into exchange_value(id,currency_from,currency_to,conversion_multiple,port)
values(10003,'AUD','INR',25,0);

/spring-boot-microservice-forex-service/src/test/java/com/in28minutes/springboot/microservice/example/forex/SpringBootMicroserviceForexServiceApplicationTests.java


package com.in28minutes.springboot.microservice.example.forex;

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 SpringBootMicroserviceForexServiceApplicationTests {

  @Test
  public void contextLoads() {
  }

}


Tags:
Hubs:
+2
Comments0

Articles