JavaRush /جاوا بلاگ /Random-UR /ہوائی ٹکٹ کی قیمت کی نگرانی کا نظام بنانا: مرحلہ وار گائی...

ہوائی ٹکٹ کی قیمت کی نگرانی کا نظام بنانا: مرحلہ وار گائیڈ [حصہ 1]

گروپ میں شائع ہوا۔

مواد:

ہوائی ٹکٹ کی قیمتوں کی نگرانی کے لیے ایک نظام بنانا: مرحلہ وار گائیڈ [حصہ 1] - 1سب کو ہیلو، JavaRush کمیونٹی! آج ہم اس بات کے بارے میں بات کریں گے کہ ہوائی ٹکٹ کی قیمتوں کی مرحلہ وار نگرانی کے لیے اسپرنگ بوٹ ایپلی کیشن کیسے لکھی جائے۔ مضمون ان لوگوں کے لیے ہے جن کے بارے میں خیال ہے:
  • REST اور کس طرح REST اینڈ پوائنٹس بنائے جاتے ہیں۔
  • متعلقہ ڈیٹا بیس؛
  • maven کا کام (خاص طور پر، انحصار کیا ہے)؛
  • JSON آبجیکٹ؛
  • لاگنگ کے اصول
متوقع رویہ:
  1. آپ ایک مخصوص تاریخ کے لیے فلائٹ منتخب کر سکتے ہیں اور اس کی قیمت کا پتہ لگا سکتے ہیں۔ صارف کی شناخت ای میل ایڈریس سے ہوتی ہے۔ جیسے ہی قیمت میں تبدیلی کی سبسکرپشن کی جاتی ہے، صارف کو ای میل کے ذریعے ایک اطلاع موصول ہوتی ہے۔
  2. ہر 30 منٹ پر (یہ وقفہ application.properties کے ذریعے ترتیب دیا جاتا ہے) تمام سبسکرپشنز کے لیے پرواز کی کم از کم قیمت کا دوبارہ حساب لگایا جاتا ہے۔ اگر ان میں سے ایک قدر کم ہو گئی ہے تو صارف کو ای میل کے ذریعے ایک اطلاع موصول ہوگی۔
  3. پرانی پرواز کی تاریخ والی تمام سبسکرپشنز کو حذف کر دیا جائے گا۔
  4. REST API کے ذریعے آپ یہ کر سکتے ہیں:
    • سبسکرپشن بنائیں؛
    • ترمیم؛
    • تمام رکنیتیں بذریعہ ای میل وصول کریں؛
    • رکنیت حذف کریں.

مقصد کے حصول کے لیے ایکشن پلان

آپ کو اس حقیقت کے ساتھ شروع کرنے کی ضرورت ہے کہ پروازوں کے بارے میں معلومات کہیں سے لینے کی ضرورت ہے۔ عام طور پر، ویب سائٹس ایک کھلا REST API فراہم کرتی ہیں جس کے ذریعے معلومات کو بازیافت کیا جا سکتا ہے۔

API (ایپلیکیشن پروگرامنگ انٹرفیس) ایک انٹرفیس ہے جس کے ذریعے آپ کسی ایپلیکیشن کے ساتھ بات چیت کرسکتے ہیں۔ اس سے ہم ایک پل بنا سکتے ہیں کہ REST API کیا ہے۔

ایک REST API REST درخواستوں کا ایک انٹرفیس ہے جسے ویب ایپلیکیشن کے ساتھ بات چیت کرنے کے لیے استعمال کیا جا سکتا ہے۔

ایسا کرنے کے لیے، ہم Skyscanner ، یا اس کے بجائے، API ( Rakuten API ویب سائٹ پر ) استعمال کریں گے۔ اگلا، آپ کو بنیادی بنیاد کے طور پر صحیح فریم ورک کا انتخاب کرنے کی ضرورت ہے۔ سب سے زیادہ مقبول اور مانگ میں بہار ماحولیاتی نظام اور ان کی تخلیق کا تاج ہے - بہار بوٹ. آپ ان کی سرکاری ویب سائٹ پر جا سکتے ہیں، یا آپ Habré پر مضمون پڑھ سکتے ہیں ۔ صارف کی سبسکرپشنز کو ذخیرہ کرنے کے لیے ہم بلٹ ان H2 ڈیٹا بیس استعمال کریں گے ۔ JSON سے کلاسز اور پیچھے پڑھنے کے لیے، ہم جیکسن پروجیکٹ استعمال کریں گے ( ہمارے وسائل پر لنک یہ ہے )۔ ہم صارفین کو پیغامات بھیجنے کے لیے spring-boot-starter-mail کا استعمال کریں گے ۔ ایپلیکیشن کو دی گئی فریکوئنسی پر کم از کم قیمت کا دوبارہ حساب لگانے کے لیے، ہم Spring Scheduler استعمال کریں گے ۔ ایک REST API بنانے کے لیے ہم spring-boot-starter-web استعمال کریں گے ۔ مستعار شدہ کوڈ (getters، setters، override equals اور hashcode، toString() اشیاء کے لیے نہ لکھنے کے لیے ، ہم Project Lombok استعمال کریں گے ۔ REST API کو محسوس کرنے اور دیکھنے کے لیے، ہم ریئل ٹائم ٹریکنگ کے لیے Swagger 2 اور فوری طور پر Swagger UI (یوزر انٹرفیس) استعمال کریں گے۔ یہ اب کیسا لگتا ہے: ہوائی ٹکٹ کی قیمت کی نگرانی کا نظام بنانا: مرحلہ وار گائیڈ [حصہ 1] - 2جہاں 4 باقی سوالات ہیں جو سبسکرپشنز بنانے، ترمیم کرنے، حاصل کرنے اور حذف کرنے سے متعلق ہیں۔

Skyscanner API کو دریافت کرنا

آئیے rakuten api کے لنک پر عمل کریں ۔ سب سے پہلے آپ کو رجسٹر کرنے کی ضرورت ہے۔ ہوائی ٹکٹ کی قیمت کی نگرانی کا نظام بنانا: مرحلہ وار گائیڈ [حصہ 1] - 3یہ سب اپنی سائٹ کو استعمال کرنے اور اس پر پوسٹ کیے گئے عوامی APIs سے درخواستیں کرنے کے لیے ایک منفرد کلید حاصل کرنے کے لیے ضروری ہے۔ ان APIs میں سے ایک Skyscanner Flight Search ہے جس کی ہمیں ضرورت ہے ۔ اب آئیے معلوم کریں کہ یہ کیسے کام کرتا ہے۔ آئیے GET List Places کی درخواست تلاش کریں۔ تصویر سے پتہ چلتا ہے کہ آپ کو ڈیٹا بھرنے اور ٹیسٹ اینڈ پوائنٹ کو شروع کرنے کی ضرورت ہے، جس کے نتیجے میں ہمیں دائیں طرف JSON آبجیکٹ کی شکل میں جواب موصول ہوتا ہے: ہوائی ٹکٹ کی قیمتوں کی نگرانی کے لیے ایک نظام بنانا: مرحلہ وار گائیڈ [حصہ 1] - 4اور درخواست اس طرح بنائی جائے گی:

https://skyscanner-skyscanner-flight-search-v1.p.rapidapi.com/apiservices/autosuggest/v1.0/{country}/{currency}/{locale}/?query={query}
اور تمام پیرامیٹرز کو اس فارمولے میں بدل دیا جائے گا، ہمیں ملتا ہے:

https://skyscanner-skyscanner-flight-search-v1.p.rapidapi.com/apiservices/autosuggest/v1.0/UK/GBP/en-GB/?query=Stockholm
اور ان درخواستوں پر دو ہیڈر بھیجے جائیں گے:

.header("x-rapidapi-host", "skyscanner-skyscanner-flight-search-v1.p.rapidapi.com")
.header("x-rapidapi-key", "sing-up-for-key"),
جہاں sign-up-for-keyاسے رجسٹریشن کے بعد جاری کیا جاتا ہے۔ قیمت میں کمی کو ٹریک کرنے کے لیے، ہمیں براؤز کوٹس اینڈ پوائنٹ کی ضرورت ہوگی۔ اسے خود تلاش کریں :)

اسپرنگ بوٹ پر مبنی ایپلیکیشن فریم ورک بنانا

Spring Boot کے ساتھ تیزی سے اور آسانی سے پروجیکٹ بنانے کے لیے، آپ Spring Initializr استعمال کر سکتے ہیں ۔ درج ذیل اختیارات کو منتخب کریں:
  1. ماون پروجیکٹ
  2. جاوا
  3. 2.1.10
  4. گروپ - جو بھی آپ کے خیال میں ضروری ہے، مثال کے طور پر ru.javarush
  5. آرٹفیکٹ - بالکل وہی، مثال کے طور پر پروازوں کی نگرانی
  6. انحصار کی تلاش میں ہم مندرجہ ذیل تلاش کرتے ہیں:
    • اسپرنگ ویب
    • جاوا میل بھیجنے والا
    • اسپرنگ ڈیٹا جے پی اے
    • H2 ڈیٹا بیس
اور پھر جنریٹ پر کلک کریں ۔ بس: تیار شدہ پروجیکٹ کو آرکائیو کے طور پر ڈاؤن لوڈ کیا جائے گا۔ اگر کچھ کام نہیں کرتا ہے، تو آپ اس لنک کو استعمال کرسکتے ہیں جہاں میں نے مطلوبہ پروجیکٹ کو محفوظ کیا تھا ۔ یقیناً، بہتر ہے کہ یہ خود کریں اور سمجھیں کہ یہ کیسے کام کرتا ہے۔ درخواست تین پرتوں پر مشتمل ہوگی:
  • کنٹرولر - درخواست میں لاگ ان کریں۔ REST API کو یہاں بیان کیا جائے گا۔
  • SERVICE ایک کاروباری منطق کی تہہ ہے۔ درخواست کی پوری منطق یہاں بیان کی جائے گی۔
  • REPOSITORY - ڈیٹا بیس کے ساتھ کام کرنے کے لیے پرت۔
اس کے علاوہ، Skyscanner Flight Search API کے کلائنٹ سے متعلق کلاسز ایک الگ پیکج ہوں گی۔

ہم پروجیکٹ میں Skyscanner Flight Search API کو درخواستوں کے لیے ایک کلائنٹ لکھ رہے ہیں۔

Skyscanner نے مہربانی کرکے ایک مضمون فراہم کیا ہے کہ ان کے API کو کیسے استعمال کیا جائے (ہم ایک فعال درخواست کے ساتھ سیشن نہیں بنائیں گے)۔ "کلائنٹ لکھنے" کا کیا مطلب ہے؟ ہمیں مخصوص پیرامیٹرز کے ساتھ ایک مخصوص URL پر ایک درخواست بنانے کی ضرورت ہے اور ہمیں واپس منتقل کیے گئے ڈیٹا کے لیے DTO (ڈیٹا ٹرانسفر آبجیکٹ) تیار کرنا ہوگا۔ سائٹ پر درخواستوں کے چار گروپ ہیں:
  1. براہ راست پرواز کی تلاش - ہم اس وقت اسے غیر ضروری نہیں سمجھیں گے۔
  2. مقامات - چلو لکھتے ہیں.
  3. پرواز کی قیمتیں براؤز کریں - ہم ایک درخواست استعمال کریں گے جہاں آپ تمام معلومات حاصل کر سکتے ہیں۔
  4. لوکلائزیشن - آئیے اسے شامل کریں تاکہ ہمیں معلوم ہو کہ کون سا ڈیٹا سپورٹ ہے۔

لوکلائزیشن کی درخواست کے لیے ایک کلائنٹ سروس بنائیں:

منصوبہ ایک ابلی ہوئی شلجم کی طرح آسان ہے: ایک درخواست بنائیں، پیرامیٹرز کو دیکھیں، جواب دیکھیں۔ دو سوالات ہیں: فہرست مارکر اور کرنسی۔ آئیے کرنسیوں کے ساتھ شروع کرتے ہیں۔ اعداد و شمار سے پتہ چلتا ہے کہ یہ اضافی فیلڈز کے بغیر ایک درخواست ہے: معاون کرنسیوں کے بارے میں معلومات حاصل کرنے کے لیے اس کی ضرورت ہے: ہوائی ٹکٹ کی قیمت کی نگرانی کا نظام بنانا: مرحلہ وار گائیڈ [حصہ 1] - 6جواب JSON آبجیکٹ کی شکل میں ہے، جس میں انہی اشیاء کا مجموعہ ہے، مثال کے طور پر:
{
"Code":"LYD"
"Symbol":"د.ل.‏"
"ThousandsSeparator":","
"DecimalSeparator":"."
"SymbolOnLeft":true
"SpaceBetweenAmountAndSymbol":false
"RoundingCoefficient":0
"DecimalDigits":3
}
آئیے اس آبجیکٹ کے لیے کرنسی ڈی ٹو بنائیں:
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;
}
کہاں:
  • @Data Lombok پروجیکٹ کی ایک تشریح ہے اور تمام گیٹرز، سیٹرز، اوور رائیڈ ٹو سٹرنگ()، equals() اور hashCode() طریقے تیار کرتی ہے۔ کیا کوڈ پڑھنے کی اہلیت کو بہتر بناتا ہے اور POJO اشیاء کو لکھنے کے وقت کو تیز کرتا ہے ۔
  • @JsonProperty("Code") جیکسن پروجیکٹ کی ایک تشریح ہے جو بتاتی ہے کہ اس متغیر کو کون سا فیلڈ تفویض کیا جائے گا۔ یعنی، کوڈ کے برابر JSON میں ایک فیلڈ کوڈ متغیر کو تفویض کیا جائے گا ۔
Skyscanner کا سرکاری مضمون REST درخواستوں کے لیے UniRest لائبریری کا استعمال کرنے کا مشورہ دیتا ہے ۔ لہذا، ہم ایک اور سروس لکھیں گے جو REST کے ذریعے درخواستوں کو نافذ کرے گی۔ یہ UniRestService ہو گی ۔ ایسا کرنے کے لیے، maven میں ایک نیا انحصار شامل کریں:
<dependency>
  <groupId>com.mashape.unirest</groupId>
  <artifactId>unirest-java</artifactId>
  <version>1.4.9</version>
</dependency>
اگلا، ہم ایک خدمت لکھیں گے جو REST درخواستوں کو انجام دے گی۔ یقیناً، ہر کلائنٹ/سروس کے لیے ہم ایک انٹرفیس اور اس کا نفاذ بنائیں گے:
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);

}
اور اس کا نفاذ:
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;
   }
}
اس کا خلاصہ یہ ہے کہ وہ تمام درخواستیں جن میں ہماری دلچسپی ہے وہ GET درخواستوں کے لیے بنائی گئی ہیں، اور یہ سروس ایک تیار شدہ درخواست کو قبول کرتی ہے اور ضروری ہیڈر شامل کرتی ہے جیسے:
.header("x-rapidapi-host", "skyscanner-skyscanner-flight-search-v1.p.rapidapi.com")
.header("x-rapidapi-key", xRapidApiKey)
پراپرٹیز سے ڈیٹا لینے کے لیے ذیل میں دکھایا گیا @Value تشریح استعمال کریں:
@Value("${x.rapid.api.key}")
private String xRapidApiKey;
اس کا کہنا ہے کہ application.properties میں x.rapid.api.key کے نام سے ایک پراپرٹی ہوگی، جسے اس متغیر میں داخل کرنے کی ضرورت ہے۔ ہم ہارڈ کوڈ شدہ اقدار سے چھٹکارا حاصل کرتے ہیں اور پروگرام کوڈ سے اس متغیر کی تعریف اخذ کرتے ہیں۔ مزید یہ کہ جب میں اس ایپلی کیشن کو GitHub پر شائع کرتا ہوں تو میں اس پراپرٹی کی قیمت شامل نہیں کرتا ہوں۔ یہ سیکورٹی وجوہات کی بناء پر کیا جاتا ہے۔ ہم نے ایک سروس لکھی ہے جو REST کی درخواستوں کے ساتھ کام کرے گی، اب وقت آگیا ہے کہ لوکلائزیشن کی خدمت کا۔ ہم OOP کی بنیاد پر ایک ایپلیکیشن بنا رہے ہیں، لہذا ہم LocalizationClient انٹرفیس اور اس کے نفاذ کو LocalisationClientImpl بناتے ہیں :
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();

}
اور LocalizationClientImpl کا نفاذ
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>>() {
       });
   }
}
کہاں
  • @Autowired ایک تشریح ہے جو کہتی ہے کہ آپ کو اس کلاس میں کسی آبجیکٹ کو انجیکشن کرنے اور اسے بنائے بغیر استعمال کرنے کی ضرورت ہے، یعنی نئے آبجیکٹ آپریشن کے بغیر؛
  • @Component ایک تشریح ہے جو کہتی ہے کہ اس آبجیکٹ کو ایپلیکیشن سیاق و سباق میں شامل کیا جانا چاہیے تاکہ اسے بعد میں @Autowired تشریح کا استعمال کرتے ہوئے انجکشن کیا جا سکے۔
  • آبجیکٹ میپر آبجیکٹ میپر جیکسن پروجیکٹ کا ایک آبجیکٹ ہے جو اس سب کو جاوا آبجیکٹ میں ترجمہ کرتا ہے۔
  • کرنسی ڈی ٹی او اور کنٹری ڈیٹو:
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;
}
پروجیکٹ کے کسی بھی حصے میں آبجیکٹ میپر لگانے کے لیے، میں نے کنفیگریشن کلاس کے ذریعے اسے ApplicationContext میں بنانا اور شامل کرنا شامل کیا۔
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 تشریح اسپرنگ کو بتاتی ہے کہ اس کلاس میں کچھ کنفیگریشنز ہوں گی۔ اور صرف اس کے لیے میں نے ObjectMapper کو شامل کیا۔ اسی طرح، ہم PlacesClient اور PlacesClientImpl شامل کرتے ہیں:
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;
}
اور
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>>() {
       });
   }
}
جہاں PlacesDto کا فارم ہے:
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;
}
اور آخر میں، ایک کلائنٹ سروس جو ضروری ڈیٹا کی بنیاد پر، پرواز کی کم از کم قیمت اور تمام ضروری معلومات واپس کرے گی: FlightPriceClient اور FlightPriceClientImpl۔ ہم صرف ایک درخواست کو لاگو کریں گے، براؤز کوٹس۔ 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 ایسا لگتا ہے:
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;
}
نتیجے کے طور پر، PlacesCl کے اعداد و شمار کے مطابق
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION