JavaRush /Java blogi /Random-UZ /Aviachiptalar narxini monitoring qilish tizimini yaratish...

Aviachiptalar narxini monitoring qilish tizimini yaratish: bosqichma-bosqich qo'llanma [1-qism]

Guruhda nashr etilgan

Tarkib:

Aviachiptalar narxlarini monitoring qilish tizimini yaratish: bosqichma-bosqich qo'llanma [1-qism] - 1Hammaga salom, JavaRush jamoasi! Bugun biz bosqichma-bosqich aviachiptalar narxlarini kuzatish uchun Spring Boot dasturini qanday yozish haqida gaplashamiz. Maqola quyidagilar haqida tasavvurga ega bo'lganlar uchun mo'ljallangan:
  • REST va REST so'nggi nuqtalari qanday qurilgan;
  • relyatsion ma'lumotlar bazalari;
  • maven ishi (xususan, qaramlik nima);
  • JSON obyekti;
  • ro'yxatga olish tamoyillari.
Kutilayotgan xatti-harakatlar:
  1. Siz ma'lum bir sana uchun parvozni tanlashingiz va uning narxini kuzatishingiz mumkin. Foydalanuvchi elektron pochta manzili orqali aniqlanadi. Narx o'zgarishiga obuna bo'lishi bilanoq, foydalanuvchi elektron pochta orqali bildirishnoma oladi.
  2. Har 30 daqiqada (bu interval application.properties orqali sozlanadi) barcha obunalar uchun parvozning minimal narxi qayta hisoblab chiqiladi. Agar qiymatlardan biri pasaygan bo'lsa, foydalanuvchi elektron pochta orqali bildirishnoma oladi.
  3. Parvoz sanasi eskirgan barcha obunalar oʻchiriladi.
  4. REST API orqali siz:
    • obuna yaratish;
    • tahrirlash;
    • barcha obunalarni elektron pochta orqali qabul qilish;
    • obunani o'chirish.

Maqsadga erishish uchun harakatlar rejasi

Parvozlar haqidagi ma'lumotni biron bir joydan olish kerakligi bilan boshlashingiz kerak. Odatda, veb-saytlar ma'lumotni olish mumkin bo'lgan ochiq REST API-ni taqdim etadi.

API (dasturlarni dasturlash interfeysi) - bu dastur bilan ishlashingiz mumkin bo'lgan interfeys. Bundan biz REST API nima ekanligiga ko'prik qurishimiz mumkin.

REST API - bu veb-ilova bilan bog'lanish uchun ishlatilishi mumkin bo'lgan REST so'rovlarining interfeysi.

Buning uchun biz Skyscanner dan , aniqrog'i, API-dan foydalanamiz ( Rakuten API veb-saytida ). Keyinchalik, asosiy poydevor sifatida to'g'ri ramkani tanlashingiz kerak. Eng mashhur va talab qilinadigan bahor ekotizimidir va ularning yaratilish toji - Spring Boot. Siz ularning rasmiy veb-saytiga kirishingiz yoki Habré-dagi maqolani o'qishingiz mumkin . Foydalanuvchi obunalarini saqlash uchun biz o'rnatilgan H2 ma'lumotlar bazasidan foydalanamiz . JSON-dan sinflarga va orqaga o'qish uchun biz Jekson loyihasidan foydalanamiz ( bu bizning manbamizdagi havola ). Biz foydalanuvchilarga xabar yuborish uchun spring-boot-starter-mail-dan foydalanamiz.Ilova berilgan chastotada minimal narxni qayta hisoblashi uchun biz Spring Scheduler-dan foydalanamiz . REST API yaratish uchun biz spring-boot-starter-web dan foydalanamiz . Qarzga olingan kodni yozmaslik uchun (ob'ektlar uchun qabul qiluvchilar, sozlagichlar, bekor qilish teng va hashcode, toString()) biz Project Lombok dan foydalanamiz . REST API-ni his qilish va ko'rish uchun biz real vaqtda kuzatish uchun Swagger 2 va darhol Swagger UI (foydalanuvchi interfeysi) dan foydalanamiz. Endi u qanday ko'rinishga ega: Aviachiptalar narxini monitoring qilish tizimini yaratish: bosqichma-bosqich qo'llanma [1-qism] - 2bu erda obunalarni yaratish, tahrirlash, olish va o'chirishga mos keladigan 4 ta dam olish so'rovi mavjud.

Skyscanner API bilan tanishish

Keling, rakuten api havolasiga o'tamiz . Avval siz ro'yxatdan o'tishingiz kerak.Bularning Aviachiptalar narxini monitoring qilish tizimini yaratish: bosqichma-bosqich qo'llanma [1-qism] - 3barchasi o'z saytidan foydalanish va unda joylashtirilgan umumiy API-larga so'rov yuborish uchun noyob kalitni olish uchun kerak. Ushbu API'lardan biri bizga kerak bo'lgan Skyscanner Flight Search dasturidir . Endi bu qanday ishlashini aniqlaymiz. Keling, GET List Places so'rovini topamiz. Rasmda siz ma'lumotlarni to'ldirishingiz va Test Endpoint ni boshlashingiz kerakligini ko'rsatadi , buning natijasida biz o'ng tomonda JSON ob'ekti ko'rinishida javob olamiz: Aviachiptalar narxlarini monitoring qilish tizimini yaratish: bosqichma-bosqich qo'llanma [1-qism] - 4va so'rov quyidagicha yaratiladi:

https://skyscanner-skyscanner-flight-search-v1.p.rapidapi.com/apiservices/autosuggest/v1.0/{country}/{currency}/{locale}/?query={query}
va barcha parametrlar ushbu formulaga almashtiriladi, biz quyidagilarni olamiz:

https://skyscanner-skyscanner-flight-search-v1.p.rapidapi.com/apiservices/autosuggest/v1.0/UK/GBP/en-GB/?query=Stockholm
va bu so'rovlarga ikkita sarlavha uzatiladi:

.header("x-rapidapi-host", "skyscanner-skyscanner-flight-search-v1.p.rapidapi.com")
.header("x-rapidapi-key", "sing-up-for-key"),
sign-up-for-keyro'yxatdan o'tgandan keyin chiqarilgan joy . Narxlarning tushishini kuzatish uchun bizga kotirovkalarni ko'rib chiqish so'nggi nuqtasi kerak bo'ladi . O'zingiz toping :)

Spring Boot asosida dastur asosini yaratish

Spring Boot bilan loyihani tez va oson yaratish uchun Spring Initializr dan foydalanishingiz mumkin . Quyidagi variantlarni tanlang:
  1. Maven loyihasi
  2. Java
  3. 2.1.10
  4. guruh - qaysi biri zarur deb hisoblasangiz, masalan ru.javarush
  5. artefakt - xuddi shunday, masalan, parvozlarni kuzatish
  6. qaramlik qidiruvida biz quyidagilarni qidiramiz:
    • Bahor veb
    • Java pochta jo'natuvchisi
    • Spring Data Jpa
    • H2 ma'lumotlar bazasi
Va keyin "Yaratish" ni bosing . Hammasi: tugallangan loyiha arxiv sifatida yuklab olinadi. Agar biror narsa ishlamasa, men kerakli loyihani saqlagan havoladan foydalanishingiz mumkin . Albatta, buni o'zingiz qilish va uning qanday ishlashini tushunish yaxshiroqdir. Ilova uchta qatlamdan iborat bo'ladi:
  • CONTROLLER - ilovaga kirish. REST API bu yerda tasvirlanadi
  • XIZMAT - bu biznes mantiqiy qatlami. Ilovaning butun mantig'i bu erda tasvirlanadi.
  • REPOSITORY - ma'lumotlar bazasi bilan ishlash uchun qatlam.
Shuningdek, Skyscanner Flight Search API uchun mijozga tegishli sinflar alohida paket bo'ladi.

Loyihada Skyscanner Flight Search API-ga so'rovlar uchun mijoz yozyapmiz

Skyscanner o'z API-dan qanday foydalanish haqida maqola taqdim etdi (biz faol so'rov bilan sessiya yaratmaymiz). "Mijoz yozish" nimani anglatadi? Biz ma'lum parametrlarga ega ma'lum bir URL manziliga so'rov yaratishimiz va bizga qaytarib yuborilgan ma'lumotlar uchun DTO (ma'lumotlarni uzatish ob'ekti) ni tayyorlashimiz kerak. Saytda so'rovlarning to'rtta guruhi mavjud:
  1. Jonli parvozlarni qidirish - biz buni hozircha keraksiz deb hisoblamaymiz.
  2. Joylar - yozaylik.
  3. Parvoz narxlarini ko'rib chiqing - biz barcha ma'lumotlarni olishingiz mumkin bo'lgan bitta so'rovdan foydalanamiz.
  4. Lokalizatsiya - keling, qanday ma'lumotlar qo'llab-quvvatlanishini bilishimiz uchun uni qo'shamiz.

Mahalliylashtirish so'rovi uchun mijoz xizmatini yarating:

Reja bug'langan sholg'om kabi oddiy: so'rov yarating, parametrlarga qarang, javobga qarang. Ikkita so'rov mavjud: Ro'yxat belgilari va Valyutalar. Valyutalardan boshlaylik. Rasmda bu qo'shimcha maydonlarsiz so'rov ekanligini ko'rsatadi: qo'llab-quvvatlanadigan valyutalar haqida ma'lumot olish uchun kerak: Aviachiptalar narxini monitoring qilish tizimini yaratish: bosqichma-bosqich qo'llanma [1-qism] - 6Javob bir xil ob'ektlar to'plamini o'z ichiga olgan JSON ob'ekti shaklida, masalan:
{
"Code":"LYD"
"Symbol":"د.ل.‏"
"ThousandsSeparator":","
"DecimalSeparator":"."
"SymbolOnLeft":true
"SpaceBetweenAmountAndSymbol":false
"RoundingCoefficient":0
"DecimalDigits":3
}
Keling, ushbu obyekt uchun CurrencyDto yarataylik:
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

/**
* Data transfer object for Currency.
*/
@Data
public class CurrencyDto {

   @JsonProperty("Code")
   private String code;

   @JsonProperty("Symbol")
   private String symbol;

   @JsonProperty("ThousandsSeparator")
   private String thousandsSeparator;

   @JsonProperty("DecimalSeparator")
   private String decimalSeparator;

   @JsonProperty("SymbolOnLeft")
   private boolean symbolOnLeft;

   @JsonProperty("SpaceBetweenAmountAndSymbol")
   private boolean spaceBetweenAmountAndSymbol;

   @JsonProperty("RoundingCoefficient")
   private int roundingCoefficient;

   @JsonProperty("DecimalDigits")
   private int decimalDigits;
}
Qayerda:
  • @Data Lombok loyihasining izohidir va barcha qabul qiluvchilar, sozlagichlar, toString(), equals() va hashCode() usullarini bekor qiladi. Nima kodni o'qishni yaxshilaydi va POJO ob'ektlarini yozish vaqtini tezlashtiradi ;
  • @JsonProperty("Kod") bu o'zgaruvchiga qaysi maydon tayinlanishini bildiruvchi Jekson loyihasining izohidir. Ya'ni, kod o'zgaruvchisiga JSON'dagi kodga teng maydon tayinlanadi .
Skyscanner-ning rasmiy maqolasi REST so'rovlari uchun UniRest kutubxonasidan foydalanishni taklif qiladi . Shuning uchun biz REST orqali so'rovlarni amalga oshiradigan boshqa xizmatni yozamiz. Bu UniRestService bo'ladi . Buni amalga oshirish uchun mavenga yangi qaramlik qo'shing:
<dependency>
  <groupId>com.mashape.unirest</groupId>
  <artifactId>unirest-java</artifactId>
  <version>1.4.9</version>
</dependency>
Keyinchalik, biz REST so'rovlarini bajaradigan xizmatni yozamiz. Albatta, har bir mijoz/xizmat uchun biz interfeys va uni amalga oshirishni yaratamiz:
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;

/**
* Service, which is manipulating with Rest calls.
*/
public interface UniRestService {

   /**
   * Create GET request based on provided {@param path} with needed headers.
   *
   * @param path provided path with all the needed data
   * @return {@link HttpResponse<jsonnode>} response object.
   */
   HttpResponse<jsonnode> get(String path);

}
Va uni amalga oshirish:
import com.github.romankh3.flightsmonitoring.exception.FlightClientException;
import com.github.romankh3.flightsmonitoring.client.service.UniRestService;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
* {@inheritDoc}
*/
@Slf4j
@Service
public class UniRestServiceImpl implements UniRestService {

   public static final String HOST = "https://skyscanner-skyscanner-flight-search-v1.p.rapidapi.com";

   public static final String PLACES_FORMAT = "/apiservices/autosuggest/v1.0/%s/%s/%s/?query=%s";
   public static final String CURRENCIES_FORMAT = "/apiservices/reference/v1.0/currencies";
   public static final String COUNTRIES_FORMAT = "/apiservices/reference/v1.0/countries/%s";

   public static final String PLACES_KEY = "Places";
   public static final String CURRENCIES_KEY = "Currencies";
   public static final String COUNTRIES_KEY = "Countries";

   @Value("${x.rapid.api.key}")
   private String xRapidApiKey;

   /**
    * {@inheritDoc}
    */
   @Override
   public HttpResponse<jsonnode> get(String path) {
       HttpResponse<jsonnode> response = null;
       try {
           response = Unirest.get(HOST + path)
                   .header("x-rapidapi-host", "skyscanner-skyscanner-flight-search-v1.p.rapidapi.com")
                   .header("x-rapidapi-key", xRapidApiKey)
                   .asJson();
       } catch (UnirestException e) {
           throw new FlightClientException(String.format("Request failed, path=%s", HOST + path), e);
       }

       log.info("Response from Get request, on path={}, statusCode={}, response={}", path, response.getStatus(), response.getBody().toString());
       return response;
   }
}
Uning mohiyati shundaki, bizni qiziqtirgan barcha so'rovlar GET so'rovlari uchun yaratilgan va bu xizmat tayyor so'rovni qabul qiladi va quyidagi kabi kerakli sarlavhalarni qo'shadi:
.header("x-rapidapi-host", "skyscanner-skyscanner-flight-search-v1.p.rapidapi.com")
.header("x-rapidapi-key", xRapidApiKey)
Xususiyatlardan ma'lumotlarni olish uchun quyida ko'rsatilgandek @Value izohidan foydalaning:
@Value("${x.rapid.api.key}")
private String xRapidApiKey;
Unda aytilishicha, application.properties da x.rapid.api.key nomli xususiyat bo'ladi, bu o'zgaruvchiga kiritilishi kerak. Biz qattiq kodlangan qiymatlardan xalos bo'lamiz va ushbu o'zgaruvchining ta'rifini dastur kodidan olamiz. Bundan tashqari, men ushbu ilovani GitHub-da nashr qilganimda, men ushbu xususiyatning qiymatini qo'shmayman. Bu xavfsizlik nuqtai nazaridan amalga oshiriladi. Biz REST so'rovlari bilan ishlaydigan xizmatni yozdik, endi mahalliylashtirish xizmatiga vaqt keldi. Biz OOP asosida dastur yaratmoqdamiz, shuning uchun biz LocalizationClient interfeysini va uni LocalisationClientImpl amalga oshirishni yaratamiz :
import com.github.romankh3.flightsmonitoring.client.dto.CountryDto;
import com.github.romankh3.flightsmonitoring.client.dto.CurrencyDto;
import java.io.IOException;
import java.util.List;

/**
* Client for SkyScanner localisation.
*/
public interface LocalisationClient {

   /**
    * Retrieve the market countries that SkyScanner flight search API support. Most suppliers (airlines,
    * travel agents and car hire dealers) set their fares based on the market (or country of purchase).
    * It is therefore necessary to specify the market country in every query.
    *
    * @param locale locale of the response.
    *
    * @return the collection of the {@link CountryDto} objects.
    *
    * @throws IOException
    */
   List<CountryDto> retrieveCountries(String locale);

   /**
    * Retrieve the currencies that we ScyScanner flight search API.
    *
    * @return the collection of the {@link CurrencyDto} objects.
    *
    * @throws IOException
    */
   List<CurrencyDto> retrieveCurrencies();

}
va LocalizationClientImpl dasturini amalga oshirish
import static com.github.romankh3.flightsmonitoring.client.service.impl.UniRestServiceImpl.COUNTRIES_FORMAT;
import static com.github.romankh3.flightsmonitoring.client.service.impl.UniRestServiceImpl.COUNTRIES_KEY;
import static com.github.romankh3.flightsmonitoring.client.service.impl.UniRestServiceImpl.CURRENCIES_FORMAT;
import static com.github.romankh3.flightsmonitoring.client.service.impl.UniRestServiceImpl.CURRENCIES_KEY;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.romankh3.flightsmonitoring.client.dto.CountryDto;
import com.github.romankh3.flightsmonitoring.client.dto.CurrencyDto;
import com.github.romankh3.flightsmonitoring.client.service.LocalisationClient;
import com.github.romankh3.flightsmonitoring.client.service.UniRestService;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.exceptions.UnirestException;
import java.io.IOException;
import java.util.List;
import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
* {@inheritDoc}
*/
@Component
public class LocalisationClientImpl implements LocalisationClient {

   @Autowired
   private UniRestService uniRestService;

   @Autowired
   private ObjectMapper objectMapper;

   /**
    * {@inheritDoc}
    */
   @Override
   public List<CountryDto> retrieveCountries(String locale) throws IOException {
       HttpResponse<JsonNode> response = uniRestService.get(String.format(COUNTRIES_FORMAT, locale));

       if (response.getStatus() != HttpStatus.SC_OK) {
           return null;
       }

       String jsonList = response.getBody().getObject().get(COUNTRIES_KEY).toString();

       return objectMapper.readValue(jsonList, new TypeReference<List<CountryDto>>() {
       });
   }

   /**
    * {@inheritDoc}
    */
   @Override
   public List<CurrencyDto> retrieveCurrencies() throws IOException, UnirestException {

       HttpResponse<JsonNode> response = uniRestService.get(CURRENCIES_FORMAT);
       if (response.getStatus() != HttpStatus.SC_OK) {
           return null;
       }

       String jsonList = response.getBody().getObject().get(CURRENCIES_KEY).toString();

       return objectMapper.readValue(jsonList, new TypeReference<List<CurrencyDto>>() {
       });
   }
}
Qayerda
  • @Autowired - bu sinfga ob'ektni kiritish va uni yaratmasdan, ya'ni yangi Object operatsiyasisiz foydalanish kerakligini aytadigan annotatsiya;
  • @Component - bu ob'ektni keyinchalik @Autowired izohi yordamida kiritish uchun ilova kontekstiga qo'shilishi kerakligini aytadigan izoh;
  • ObjectMapper objectMapper - bularning barchasini Java ob'ektlariga tarjima qiladigan Jekson loyihasi ob'ekti.
  • CurrencyDTO va CountryDto:
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

/**
* Data transfer object for Currency.
*/
@Data
public class CurrencyDto {

   @JsonProperty("Code")
   private String code;

   @JsonProperty("Symbol")
   private String symbol;

   @JsonProperty("ThousandsSeparator")
   private String thousandsSeparator;

   @JsonProperty("DecimalSeparator")
   private String decimalSeparator;

   @JsonProperty("SymbolOnLeft")
   private boolean symbolOnLeft;

   @JsonProperty("SpaceBetweenAmountAndSymbol")
   private boolean spaceBetweenAmountAndSymbol;

   @JsonProperty("RoundingCoefficient")
   private int roundingCoefficient;

   @JsonProperty("DecimalDigits")
   private int decimalDigits;
}
	и
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

/**
* Data transfer object for Country.
*/
@Data
public class CountryDto {

   @JsonProperty("Code")
   private String code;

   @JsonProperty("Name")
   private String name;
}
ObjectMapper-ni loyihaning istalgan qismiga kiritish uchun men konfiguratsiya sinfi orqali uni ApplicationContext-ga yaratish va qo'shishni qo'shdim.
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* {@link Configuration} class.
*/
@Configuration
public class Config {

   @Bean
   public ObjectMapper objectMapper() {
       ObjectMapper objectMapper = new ObjectMapper();
       objectMapper.registerModule(new JavaTimeModule());
       return objectMapper;
   }
}
@Configuration izohi Bahorga ushbu sinfda ba'zi konfiguratsiyalar bo'lishini aytadi. Buning uchun men ObjectMapper-ni qo'shdim. Xuddi shunday, biz PlacesClient va PlacesClientImpl qo'shamiz:
import com.github.romankh3.flightsmonitoring.client.dto.PlaceDto;
import com.github.romankh3.flightsmonitoring.client.dto.PlacesDto;
import com.mashape.unirest.http.exceptions.UnirestException;
import java.io.IOException;
import java.util.List;

/**
* SkyScanner client.
*/
public interface PlacesClient {

   /**
    * Get a list of places that match a query string based on arguments.
    *
    * @param query the code of the city.
    * @param country the code of the country.
    * @param currency the code of the currency.
    * @param locale the code of the locale.
    * @return the collection of the {@link PlaceDto} objects.
    */
   List<PlacesDto> retrieveListPlaces(String query, String country, String currency, String locale)
           throws IOException, UnirestException;
}
va
import static com.github.romankh3.flightsmonitoring.client.service.impl.UniRestServiceImpl.PLACES_FORMAT;
import static com.github.romankh3.flightsmonitoring.client.service.impl.UniRestServiceImpl.PLACES_KEY;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.romankh3.flightsmonitoring.client.dto.PlacesDto;
import com.github.romankh3.flightsmonitoring.client.service.PlacesClient;
import com.github.romankh3.flightsmonitoring.client.service.UniRestService;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.exceptions.UnirestException;
import java.io.IOException;
import java.util.List;
import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
* {@inheritDoc}
*/
@Service
public class PlacesClientImpl implements PlacesClient {

   @Autowired
   private UniRestService uniRestService;

   @Autowired
   private ObjectMapper objectMapper;


   /**
    * {@inheritDoc}
    */
   @Override
   public List<PlacesDto> retrieveListPlaces(String query, String country, String currency, String locale)
           throws IOException, UnirestException {
       HttpResponse<JsonNode> response = uniRestService
               .get(String.format(PLACES_FORMAT, country, currency, locale, query));

       if (response.getStatus() != HttpStatus.SC_OK) {
           return null;
       }

       String jsonList = response.getBody().getObject().get(PLACES_KEY).toString();

       return objectMapper.readValue(jsonList, new TypeReference<List<PlacesDto>>() {
       });
   }
}
bu erda PlacesDto quyidagi shaklga ega:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.github.romankh3.flightsmonitoring.client.service.PlacesClient;
import lombok.Data;

/**
* Using for {@link PlacesClient}.
*/
@Data
public class PlacesDto {

   @JsonProperty("PlaceId")
   private String placeId;

   @JsonProperty("PlaceName")
   private String placeName;

   @JsonProperty("CountryId")
   private String countryId;

   @JsonProperty("RegionId")
   private String regionId;

   @JsonProperty("CityId")
   private String cityId;

   @JsonProperty("CountryName")
   private String countryName;
}
Va nihoyat, kerakli ma'lumotlarga asoslanib, parvoz uchun minimal narxni va barcha kerakli ma'lumotlarni qaytaradigan mijoz xizmati: FlightPriceClient va FlightPriceClientImpl. Biz faqat bitta so'rovni bajaramiz, browseQuotes. FlightPriceClient:
import com.github.romankh3.flightsmonitoring.client.dto.FlightPricesDto;

/**
* Browse flight prices.
*/
public interface FlightPricesClient {

   /**
    * Browse quotes for current flight based on provided arguments. One-way ticket.
    *
    * @param country the country from
    * @param currency the currency to get price
    * @param locale locale for the response
    * @param originPlace origin place
    * @param destinationPlace destination place
    * @param outboundPartialDate outbound date
    * @return {@link FlightPricesDto} object.
    */
   FlightPricesDto browseQuotes(String country, String currency, String locale, String originPlace,
           String destinationPlace, String outboundPartialDate);

   /**
    * Browse quotes for current flight based on provided arguments. Round trip ticket.
    *
    * @param country the country from
    * @param currency the currency to get price
    * @param locale locale for the response
    * @param originPlace origin place
    * @param destinationPlace destination place
    * @param outboundPartialDate outbound date
    * @param inboundPartialDate inbound date
    * @return {@link FlightPricesDto} object.
    */
   FlightPricesDto browseQuotes(String country, String currency, String locale, String originPlace,
           String destinationPlace, String outboundPartialDate, String inboundPartialDate);
}
FlightPriceClientImpl
import static com.github.romankh3.flightsmonitoring.client.service.impl.UniRestServiceImpl.CURRENCIES_KEY;
import static com.github.romankh3.flightsmonitoring.client.service.impl.UniRestServiceImpl.PLACES_KEY;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.romankh3.flightsmonitoring.client.dto.CarrierDto;
import com.github.romankh3.flightsmonitoring.client.dto.CurrencyDto;
import com.github.romankh3.flightsmonitoring.client.dto.FlightPricesDto;
import com.github.romankh3.flightsmonitoring.client.dto.PlaceDto;
import com.github.romankh3.flightsmonitoring.client.dto.QuoteDto;
import com.github.romankh3.flightsmonitoring.client.dto.ValidationErrorDto;
import com.github.romankh3.flightsmonitoring.client.service.FlightPricesClient;
import com.github.romankh3.flightsmonitoring.client.service.UniRestService;
import com.github.romankh3.flightsmonitoring.exception.FlightClientException;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import java.io.IOException;
import java.util.List;
import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
* {@inheritDoc}
*/
@Service
public class FlightPricesClientImpl implements FlightPricesClient {

   public static final String BROWSE_QUOTES_FORMAT = "/apiservices/browsequotes/v1.0/%s/%s/%s/%s/%s/%s";
   public static final String OPTIONAL_BROWSE_QUOTES_FORMAT = BROWSE_QUOTES_FORMAT + "?inboundpartialdate=%s";

   public static final String QUOTES_KEY = "Quotes";
   public static final String ROUTES_KEY = "Routes";
   public static final String DATES_KEY = "Dates";
   public static final String CARRIERS_KEY = "Carriers";
   public static final String VALIDATIONS_KEY = "ValidationErrors";

   @Autowired
   private UniRestService uniRestService;

   @Autowired
   private ObjectMapper objectMapper;

   /**
    * {@inheritDoc}
    */
   @Override
   public FlightPricesDto browseQuotes(String country, String currency, String locale, String originPlace,
           String destinationPlace, String outboundPartialDate) {

       HttpResponse<JsonNode> response = uniRestService.get(String
               .format(BROWSE_QUOTES_FORMAT, country, currency, locale, originPlace, destinationPlace,
                       outboundPartialDate));
       return mapToObject(response);
   }

   public FlightPricesDto browseQuotes(String country, String currency, String locale, String originPlace,
           String destinationPlace, String outboundPartialDate, String inboundPartialDate) {
       HttpResponse<JsonNode> response = uniRestService.get(String
               .format(OPTIONAL_BROWSE_QUOTES_FORMAT, country, currency, locale, originPlace, destinationPlace,
                       outboundPartialDate, inboundPartialDate));
       return mapToObject(response);
   }

   private FlightPricesDto mapToObject(HttpResponse<JsonNode> response) {
       if (response.getStatus() == HttpStatus.SC_OK) {
           FlightPricesDto flightPricesDto = new FlightPricesDto();
           flightPricesDto.setQuotas(readValue(response.getBody().getObject().get(QUOTES_KEY).toString(),
                   new TypeReference<List<QuoteDto>>() {
                   }));
           flightPricesDto.setCarriers(readValue(response.getBody().getObject().get(CARRIERS_KEY).toString(),
                   new TypeReference<List<CarrierDto>>() {
                   }));
           flightPricesDto.setCurrencies(readValue(response.getBody().getObject().get(CURRENCIES_KEY).toString(),
                   new TypeReference<List<CurrencyDto>>() {
                   }));
           flightPricesDto.setPlaces(readValue(response.getBody().getObject().get(PLACES_KEY).toString(),
                   new TypeReference<List<PlaceDto>>() {
                   }));
           return flightPricesDto;
       }
       throw new FlightClientException(String.format("There are validation errors. statusCode = %s", response.getStatus()),
               readValue(response.getBody().getObject().get(VALIDATIONS_KEY).toString(),
                       new TypeReference<List<ValidationErrorDto>>() {
                       }));
   }

   private <T> List<T> readValue(String resultAsString, TypeReference<List<T>> valueTypeRef) {
       List<T> list;
       try {
           list = objectMapper.readValue(resultAsString, valueTypeRef);
       } catch (IOException e) {
           throw new FlightClientException("Object Mapping failure.", e);
       }
       return list;
   }
}
FlightClientException bu erda shunday ko'rinadi:
import com.github.romankh3.flightsmonitoring.client.dto.ValidationErrorDto;
import java.util.List;

/**
* A {@link RuntimeException} that is thrown in case of an flight monitoring failures.
*/
public final class FlightClientException extends RuntimeException {

   public FlightClientException(String message) {
       super(message);
   }

   public FlightClientException(String message, Throwable throwable) {
       super(message, throwable);
   }

   public FlightClientException(String message, List<ValidationErrorDto> errors) {
       super(message);
       this.validationErrorDtos = errors;
   }

   private List<ValidationErrorDto> validationErrorDtos;
}
Natijada, PlacesCl ma'lumotlariga ko'ra
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION