Створення системи моніторингу цін на авіаквитки: покрокове керівництво [Частина 1] Створення системи моніторингу цін на авіаквитки: покрокове керівництво [Частина 2]
Зміст
- Пишемо рівень Controller'ів. SubscriptionController
- Тестування програми
- Плани на розвиток
- Висновки
- Корисні посилання
Пишемо рівень Controller'ів. SubscriptionController
Останній етап - написання REST API, через який спілкуватимемося з додатком. Для цього буде використовуватися Spring boot starter web . У SubscriptionController буде 4 методи для CRUD операцій. Для контролерів є набір анотацій, за допомогою яких це працює:- @Controller — використовується для додавання до ApplicationContext;
- @RequestMapping("path") - визначає, що в цьому класі будуть REST методи, також path - шлях, на якому буде починатися запит;
- @PostMapping — для запитів POST, використовується для створення;
- @ GetMapping - для GET запитів, використовується для читання;
- @PutMapping – для PUT запитів, використовується для редагування;
- @DeleteMapping — для DELETE запитів, що використовується для видалення;
- @PathVariable - значить змінна буде задана в URI запиту;
- @RequestBody означає, що дані будуть лежати в тілі запиту;
- @Valid - означає, що проходитиме валідація даних, якщо вони не відповідають, то буде помилка.
import com.github.romankh3.flightsmonitoring.rest.dto.SubscriptionCreateDto;
import com.github.romankh3.flightsmonitoring.rest.dto.SubscriptionDto;
import com.github.romankh3.flightsmonitoring.rest.dto.SubscriptionUpdateDto;
import com.github.romankh3.flightsmonitoring.service.SubscriptionService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.util.List;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* {@link Controller} to handle Subscriptions.
*/
@Api(value = "Operations with Subscriptions", tags = "Subscription Controller")
@RequestMapping(SubscriptionController.SUBSCRIPTION_CONTROLLER_EP)
@Controller
public class SubscriptionController {
public static final String SUBSCRIPTION_CONTROLLER_EP = "/subscription";
@Autowired
private SubscriptionService subscriptionService;
@ApiOperation("Create new subscription based on SubscriptionDto")
@PostMapping
public @ResponseBody
SubscriptionDto create(@RequestBody @Valid SubscriptionCreateDto dto) {
return subscriptionService.create(dto);
}
@ApiOperation("Finds all subscriptions based on email")
@GetMapping("/{email}")
public @ResponseBody
List<SubscriptionDto> findByEmail(@PathVariable final String email) {
return subscriptionService.findByEmail(email);
}
@ApiOperation("Updates subscription based on it ID")
@PutMapping("/{id}")
public SubscriptionDto update(@PathVariable final Long id,
@RequestBody @Valid SubscriptionUpdateDto dto) {
return subscriptionService.update(id, dto);
}
@ApiOperation("Deletes subscription based on it ID")
@DeleteMapping("/{id}")
public void delete(@PathVariable final Long id) {
subscriptionService.delete(id);
}
}
Також визначимо які нові класи DTO додалися:
-
SubscriptionCreateDto
import com.fasterxml.jackson.annotation.JsonFormat; import com.github.romankh3.flightsmonitoring.repository.entity.Subscription; import io.swagger.annotations.ApiModelProperty; import java.time.LocalDate; import javax.validation.constraints.Email; import javax.validation.constraints.NotNull; import lombok.Data; /** * Data transfer object to create a {@link Subscription} object. */ @Data public class SubscriptionCreateDto { @NotNull @Email @ApiModelProperty(value = "Subscriber's email", example = "test@test.com") private String email; @NotNull @ApiModelProperty(value = "Country Code", example = "UA") private String country; @NotNull @ApiModelProperty(value = "Currency Code", example = "UAH") private String currency; @NotNull @ApiModelProperty(value = "Locale", example = "ru-RU") private String locale; @NotNull @ApiModelProperty(value = "Code of the origin place", example = "HRK-sky") private String originPlace; @NotNull @ApiModelProperty(value = "Code of the destination place", example = "KBP-sky") private String destinationPlace; @NotNull @JsonFormat(pattern = "yyyy-MM-dd") @ApiModelProperty(value = "Date front", example = "2019-12-18") private LocalDate outboundPartialDate; @JsonFormat(pattern = "yyyy-MM-dd") @ApiModelProperty(value = "Date back", example = "2019-12-25") private LocalDate inboundPartialDate; }
-
SubscriptionUpdateDto
import com.fasterxml.jackson.annotation.JsonFormat; import com.github.romankh3.flightsmonitoring.repository.entity.Subscription; import io.swagger.annotations.ApiModelProperty; import java.time.LocalDate; import javax.validation.constraints.Email; import javax.validation.constraints.NotNull; import lombok.Data; /** * Dto for updating {@link Subscription} object. */ @Data public class SubscriptionUpdateDto { @NotNull @Email @ApiModelProperty(value = "Subscriber's email", example = "test@test.com") private String email; @NotNull @ApiModelProperty(value = "Country Code", example = "UA") private String country; @NotNull @ApiModelProperty(value = "Currency Code", example = "UAH") private String currency; @NotNull @ApiModelProperty(value = "Locale", example = "ru-RU") private String locale; @NotNull @ApiModelProperty(value = "Code of the origin place", example = "HRK-sky") private String originPlace; @NotNull @ApiModelProperty(value = "Code of the destination place", example = "KBP-sky") private String destinationPlace; @NotNull @JsonFormat(pattern = "yyyy-MM-dd") @ApiModelProperty(value = "Date front", example = "2019-12-18") private LocalDate outboundPartialDate; @JsonFormat(pattern = "yyyy-MM-dd") @ApiModelProperty(value = "Date back", example = "2019-12-25") private LocalDate inboundPartialDate; }
-
SubscriptionDto
import com.fasterxml.jackson.annotation.JsonFormat; import com.github.romankh3.flightsmonitoring.client.dto.FlightPricesDto; import io.swagger.annotations.ApiModelProperty; import java.time.LocalDate; import javax.validation.constraints.Email; import javax.validation.constraints.NotNull; import lombok.Data; /** * Data transfer object to see all the data related to subscription. */ @Data public class SubscriptionDto { private Long id; @NotNull @Email @ApiModelProperty(value = "Subscriber's email", example = "test@test.com") private String email; @NotNull @ApiModelProperty(value = "Country Code", example = "UA") private String country; @NotNull @ApiModelProperty(value = "Currency Code", example = "UAH") private String currency; @NotNull @ApiModelProperty(value = "Locale", example = "ru-RU") private String locale; @NotNull @ApiModelProperty(value = "Code of the origin place", example = "HRK-sky") private String originPlace; @NotNull @ApiModelProperty(value = "Code of the destination place", example = "KBP-sky") private String destinationPlace; @NotNull @JsonFormat(pattern = "yyyy-MM-dd") @ApiModelProperty(value = "Date front", example = "2019-12-18") private LocalDate outboundPartialDate; @JsonFormat(pattern = "yyyy-MM-dd") @ApiModelProperty(value = "Date back", example = "2019-12-25") private LocalDate inboundPartialDate; @ApiModelProperty(value = "Min price based on all these data", example = "100") private Integer minPrice; @ApiModelProperty(value = "Response which contains all the need info about min price flight") private FlightPricesDto flightPricesDto; }
- @ Email – перевіряє на правильність написання електронної пошти;
- @NotNull - Перевіряє, що змінна не повинна бути порожньою.
Тестування програми
У статті я не описуватиму тестування. Тим не менш, тести на проекті є , і їх можна подивитися та вивчити самостійно. Більше того, якщо будуть якісь питання, можна ставити їх тут у коментарях: я із задоволенням відповім на них.Плани на розвиток
Проект уже є, і я планую займатися ним далі. У найближчому майбутньому хочу зробити таке:- написати окремо як бібліотеку клієнт для Skyscanner Flight Search, щоб можна було використовувати це як залежність у цьому проекті, а й у інших;
- перевести на PostgreSQL, щоб не губабося дані на Heroku при зупинці програми. Це зробить його стабільнішим;
- створити контролери даних клієнта, які підтримуються ним. Наприклад для Places, Currencies, Countries;
- розширити функціонал пошуку. Там є ще багато опцій;
- чекаю пропозиції від спільноти.
Висновки
Написати веб-додаток з REST API на основі Spring Boot та екосистеми загалом – це не так складно, як може здатися. Так, є нюанси, які треба знати. Щоб прояснити все, що пов'язане зі спрингом, я рекомендую прочитати Spring in Action 5th edition . Після цієї книги стане ясніше, що тут відбувається. PS її можна знайти у вк безкоштовно.Корисні посилання
Всі дані, якими я користувався при написанні проекту та просто корисні посилання для розуміння того, що добре б вивчити:- Посилання на проект: flights-monitoring .
- Посилання на розгорнутий проект на хероку .
- Sptring Initializr – швидкий спосіб сформувати проект із потрібними конфігураціями, залежностями. Посилання на сформований проект .
- Skyscanner Flight Search — відкритий API для отримання даних про польоти.
- Хабр: Введення у Spring Boot: створення простого REST API на Java .
- JavaRush: Вступ до Jackson Framework .
- JavaRush: Project Lombok, або оголошуємо війну бойлерплейту .
- Rapidapi: Skyscanner Flight Search API(Java) .
- Wiki: POJO .
- Spring Boot With H2 database .
- Вирішення проблем з Gmail для надсилання листів.
- Spring Boot - how to send email via SMTP.
- Scheduling tasks.
- Setting Up Swagger 2 with a Spring REST API.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ