«1. Введение

В этом уроке мы увидим, как мы можем создать новый API внутри приложения JHipster. Затем мы интегрируем этот API во внешний дисплей.

2. Пример приложения

В этом уроке мы будем использовать простое приложение книжного магазина.

Книжный магазин построен как монолит. Он использует Angular для внешнего интерфейса и имеет единую сущность с именем book со следующими полями:

    Название Автор Опубликованные данные Цена Количество

JHipster автоматически генерирует API и интерфейсные представления, которые обеспечивают простые операции для книги: просмотр , создавать, редактировать и удалять.

В этом руководстве мы добавим API, который позволяет пользователю покупать книгу, а также кнопку на интерфейсе, которая вызывает новый API.

Мы сосредоточимся только на API и интерфейсных аспектах покупки. Мы не будем выполнять какую-либо обработку платежей и только минимальную проверку.

3. Изменения Spring Boot

JHipster предоставляет генератор для создания новых контроллеров. Однако для этого руководства мы вручную создадим API и связанный с ним код.

3.1. Класс ресурсов

Первым шагом является обновление сгенерированного класса BookResource. Мы добавляем новую конечную точку, которую будет вызывать интерфейсный код:

@GetMapping("/books/purchase/{id}")
public ResponseEntity<BookDTO> purchase(@PathVariable Long id) {
    Optional<BookDTO> bookDTO = bookService.purchase(id);
    return ResponseUtil.wrapOrNotFound(bookDTO);
}

Это создает новую конечную точку API, расположенную по адресу /books/purchase/{id}. Единственным вводом является идентификатор книги, и мы возвращаем BookDTO, который будет отражать новый уровень запасов после покупки.

3.2. Интерфейс и класс службы

Теперь нам нужно обновить интерфейс BookService, чтобы включить новый метод покупки:

Optional<BookDTO> purchase(Long id);

Затем нам нужно реализовать новый метод в классе BookServiceImpl:

@Override
public Optional<BookDTO> purchase(Long id) {
    Optional<BookDTO> bookDTO = findOne(id);
    if (bookDTO.isPresent()) {
        int quantity = bookDTO.get().getQuantity();
        if (quantity > 0) {
            bookDTO.get().setQuantity(quantity - 1);
            Book book = bookMapper.toEntity(bookDTO.get());
            book = bookRepository.save(book);
            return bookDTO;
        }
        else {
            throw new BadRequestAlertException("Book is not in stock", "book", "notinstock");
        }
    }
    return Optional.empty();
}

Давайте посмотрите, что происходит в этом коде. Во-первых, мы ищем книгу по ее идентификатору, чтобы убедиться, что она существует. Если это не так, мы возвращаем пустой вариант.

Если он существует, мы гарантируем, что уровень его запасов больше нуля. В противном случае мы выбрасываем исключение BadRequestAlertException. Хотя это исключение обычно используется только на уровне REST JHipster, мы используем его здесь, чтобы продемонстрировать, как возвращать полезные сообщения об ошибках во внешний интерфейс.

Иначе, если запас больше нуля, то уменьшаем его на единицу, сохраняем в репозиторий и возвращаем обновленный DTO.

3.3. Конфигурация безопасности

Последнее требуемое изменение находится в классе SecurityConfiguration:

.antMatchers("/api/books/purchase/**").authenticated()

Это гарантирует, что вызовы нашего нового API разрешены только аутентифицированным пользователям.

4. Изменения внешнего интерфейса

Теперь давайте сосредоточимся на изменениях внешнего интерфейса. JHipster создает представление для отображения одной книги, и именно туда мы добавим нашу новую кнопку покупки.

4.1. Класс службы

Во-первых, нам нужно добавить новый метод в существующий файл book.service.ts. Этот файл уже содержит методы для работы с объектами книг, поэтому сейчас самое время добавить логику для нашего нового API:

purchase(id: number): Observable<EntityResponseType> {
    return this.http
        .get<IBook>(`${this.resourceUrl}/purchase/${id}`, { observe: 'response' })
        .pipe(map((res: EntityResponseType) => this.convertDateFromServer(res)));
}

4.2. Компонент

Затем нам нужно обновить код компонента в book.component.ts. Мы создадим функцию, которая вызывает новый метод в книжном сервисе Angular, а затем прослушивает ответ от сервера:

purchase(id: number) {
    this.bookService.purchase(id).subscribe(
        (res: HttpResponse<IBook>) => {
            this.book = res.body;
        },
        (res: HttpErrorResponse) => console.log(res.message)
    );
}

4.3. Представление

Наконец, мы можем добавить кнопку в представление книги, которая вызывает новый метод покупки в компоненте:

<button type="button"
             class="btn btn-primary"
             (click)="purchase(book.id)">
    <span>Purchase</span>
</button>

На изображении ниже показано обновленное представление в интерфейсе: Кнопка «Купить» приведет к вызову нашего нового API, и интерфейс автоматически обновится с новым статусом запаса (или отобразит ошибку, если что-то пошло не так).

5. Заключение

В этом руководстве мы увидели, как создавать пользовательские API в JHipster и интегрировать их во внешний интерфейс.

Мы начали с добавления API и бизнес-логики в Spring Boot. Затем мы изменили интерфейсный код, чтобы использовать новый API и отображать результаты. С небольшими усилиями мы смогли добавить новые функции поверх существующих операций CRUD, которые автоматически генерирует JHipster.

Как всегда, код доступен на GitHub.

«