เนื้อหา:
- แผนปฏิบัติการเพื่อให้บรรลุเป้าหมาย
- สำรวจ Skyscanner API
- การสร้างกรอบงานแอปพลิเคชันโดยใช้ Spring Boot
- เรากำลังเขียนคำขอไปยังลูกค้าเพื่อส่งคำขอไปยัง Skyscanner Flight Search API ในโครงการ
- การสร้างบริการลูกค้าสำหรับคำขอ Localization
- REST และวิธีสร้างจุดสิ้นสุด REST
- ฐานข้อมูลเชิงสัมพันธ์
- งานของ Maven (โดยเฉพาะการพึ่งพาคืออะไร);
- วัตถุ JSON;
- หลักการบันทึก
- คุณสามารถเลือกเที่ยวบินสำหรับวันที่เจาะจงและติดตามราคาได้ ผู้ใช้จะถูกระบุด้วยที่อยู่อีเมล ทันทีที่มีการสมัครรับข้อมูลการเปลี่ยนแปลงราคา ผู้ใช้จะได้รับการแจ้งเตือนทางอีเมล
- ทุก 30 นาที (ช่วงเวลานี้ได้รับการกำหนดค่าผ่าน application.properties) ราคาขั้นต่ำสำหรับเที่ยวบินจะถูกคำนวณใหม่สำหรับการสมัครสมาชิกทั้งหมด หากค่าใดค่าหนึ่งลดลง ผู้ใช้จะได้รับการแจ้งเตือนทางอีเมล
- การสมัครสมาชิกทั้งหมดที่มีวันที่เที่ยวบินล้าสมัยจะถูกลบ
- ผ่าน REST API คุณสามารถ:
- สร้างการสมัครสมาชิก
- แก้ไข;
- รับการสมัครสมาชิกทั้งหมดทางอีเมล
- ลบการสมัครสมาชิก
แผนปฏิบัติการเพื่อให้บรรลุเป้าหมาย
คุณต้องเริ่มต้นด้วยข้อเท็จจริงที่ว่าข้อมูลเกี่ยวกับเที่ยวบินจำเป็นต้องนำมาจากที่ไหนสักแห่ง โดยทั่วไปแล้ว เว็บไซต์จะมี REST API แบบเปิดซึ่งสามารถดึงข้อมูลได้
API (Application Programming Interface) คืออินเทอร์เฟซที่คุณสามารถโต้ตอบกับแอปพลิเคชันได้ จากนี้เราสามารถสร้างสะพานเชื่อมไปยัง REST API ได้ REST API เป็นอินเทอร์เฟซของคำขอ REST ที่สามารถใช้เพื่อสื่อสารกับเว็บแอปพลิเคชัน |
สำรวจ Skyscanner API
ไปตามลิงค์ไปยังrakuten api ก่อนอื่น คุณต้องลงทะเบียน ทั้งหมดนี้จำเป็นเพื่อรับคีย์เฉพาะเพื่อใช้ไซต์และร้องขอไปยัง API สาธารณะที่โพสต์ไว้ หนึ่งใน API เหล่านี้คือSkyscanner Flight Search ที่เรา ต้องการ ตอนนี้เรามาดูกันว่ามันทำงานอย่างไร มาหาคำขอ GET List Places กัน รูปภาพแสดงให้เห็นว่าคุณต้องกรอกข้อมูลและเริ่มTest Endpointซึ่งส่งผลให้เราได้รับการตอบกลับในรูปแบบของออบเจ็กต์ JSON ทางด้านขวา และคำขอจะถูกสร้างขึ้นดังนี้:
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 Boot อย่างรวดเร็วและง่ายดาย คุณสามารถใช้Spring Initializrได้ เลือกตัวเลือกต่อไปนี้:- โครงการมาเวน
- ชวา
- 2.1.10
- group - แล้วแต่คุณคิดว่าจำเป็น เช่น ru.javarush
- สิ่งประดิษฐ์ - เหมือนกันทุกประการ เช่น การตรวจสอบเที่ยวบิน
- ในการค้นหาการพึ่งพาเรามองหาสิ่งต่อไปนี้:
- สปริงเว็บ
- ผู้ส่งเมล Java
- สปริงดาต้า เจพีเอ
- ฐานข้อมูล H2
- ตัวควบคุม - เข้าสู่แอปพลิเคชัน REST API จะอธิบายไว้ที่นี่
- บริการเป็นชั้นตรรกะทางธุรกิจ ตรรกะทั้งหมดของแอปพลิเคชันจะอธิบายไว้ที่นี่
- พื้นที่เก็บข้อมูล - เลเยอร์สำหรับการทำงานกับฐานข้อมูล
เรากำลังเขียนคำขอไปยังลูกค้าเพื่อส่งคำขอไปยัง Skyscanner Flight Search API ในโครงการ
Skyscanner ได้กรุณาจัดเตรียมบทความเกี่ยวกับวิธีใช้ API ของพวกเขา (เราจะไม่สร้างเซสชันที่มีคำขอที่ทำงานอยู่) "เขียนลูกค้า" หมายความว่าอย่างไร? เราจำเป็นต้องสร้างคำขอไปยัง URL เฉพาะด้วยพารามิเตอร์บางอย่างและเตรียม DTO (วัตถุการถ่ายโอนข้อมูล) สำหรับข้อมูลที่ถ่ายโอนกลับมาหาเรา มีคำขอสี่กลุ่มบนเว็บไซต์:- ค้นหาเที่ยวบินสด - เราจะไม่พิจารณาว่าไม่จำเป็นในขณะนี้
- สถานที่ - มาเขียนกันเถอะ
- เรียกดูราคาเที่ยวบิน - เราจะใช้คำขอเดียวซึ่งคุณจะได้รับข้อมูลทั้งหมด
- การแปลเป็นภาษาท้องถิ่น - มาเพิ่มกันเพื่อให้เราทราบว่าข้อมูลใดบ้างที่รองรับ
สร้างบริการลูกค้าสำหรับคำขอ Localization:
แผนนี้ง่ายเหมือนหัวผักกาดนึ่ง: สร้างคำขอ ดูพารามิเตอร์ ดูการตอบสนอง มีสองคำถาม: เครื่องหมายรายการและสกุลเงิน เริ่มต้นด้วยสกุลเงิน รูปแสดงให้เห็นว่านี่เป็นคำขอที่ไม่มีฟิลด์เพิ่มเติม: จำเป็นเพื่อรับข้อมูลเกี่ยวกับสกุลเงินที่รองรับ: การตอบสนองจะอยู่ในรูปแบบของออบเจ็กต์ JSON ซึ่งมีคอลเลกชันของออบเจ็กต์เดียวกัน เช่น:{
"Code":"LYD"
"Symbol":"د.ل."
"ThousandsSeparator":","
"DecimalSeparator":"."
"SymbolOnLeft":true
"SpaceBetweenAmountAndSymbol":false
"RoundingCoefficient":0
"DecimalDigits":3
}
มาสร้าง CurrencyDto สำหรับวัตถุนี้กันดีกว่า:
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 เป็นคำอธิบายประกอบจากโปรเจ็กต์ลอมบอกและสร้างเมธอด getters, setters, overrides toString(), equals() และ hashCode() ทั้งหมด สิ่งที่ปรับปรุงความสามารถในการอ่านโค้ดและเพิ่มความเร็วในการเขียนอ็อบเจ็กต์POJO
- @JsonProperty("Code") เป็นคำอธิบายประกอบจาก Jackson Project ที่บอกว่าฟิลด์ใดจะถูกกำหนดให้กับตัวแปรนี้ นั่นคือฟิลด์ใน JSON เท่ากับ Code จะถูกกำหนดให้กับตัวแปรโค้ด
<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
- ObjectMapper objectMapper เป็นวัตถุจาก Jackson Project ที่แปลทั้งหมดนี้ลงในวัตถุ Java
- สกุลเงินDTO และประเทศDto:
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 ลงในส่วนใดๆ ของโปรเจ็กต์ ฉันได้เพิ่มการสร้างและเพิ่มลงใน 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 จะบอก Spring ว่าจะมีการกำหนดค่าบางอย่างในคลาสนี้ และเพื่อสิ่งนี้ ฉันจึงเพิ่ม 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 เราจะดำเนินการตามคำขอเดียวเท่านั้น คือ browserQuotes ราคาเที่ยวบินลูกค้า:
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);
}
เที่ยวบินราคาClientImpl
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
GO TO FULL VERSION