Закладка интерфейса AngularJS (прямой доступ) - бэкэнд Spring Data Rest

Я начал реализовывать веб-интерфейс для управления сервисом RESTful, обслуживаемым Spring Data Rest над традиционной реляционной БД. Это сделано с AngularJS и angular-hal Библиотека, которую я нашел, очень хорошо вписывается HATEOAS философия и формализм Spring Data Rest,

Например, мне просто нужно знать первую конечную точку API ('/'), а затем все мои запросы выполняются через отношения без учета URL-адресов. У меня проблема в том, чтобы иметь возможность прямого доступа к странице, отображающей одну из моих сущностей.

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

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

Корень проблемы в том, что с Spring Data Rest субъекты не имеют публичного поля для своих id (не в JSON), а репозитории не имеют API relation искать по идентификатору.

Я думал о некоторых решениях, но мне не нравится ни одно из них.

1. Обойти в бэкэнде

  • Добавить Projection с методом getId() для всех объектов, которые должны быть в закладки
  • Добавьте соответствующий findById() в интерфейсе репозитория
  • Используйте идентификатор в URL внешнего интерфейса в качестве параметра (или пути) и разрешите ресурс, вызвав новое доступное отношение поиска.
  • Недостатки: это вынуждает нас вручную переделывать все DTO, автоматически сгенерированные Spring Data Rest, поэтому мы теряем одну из целей фреймворка.
  • Вопрос: есть ли способ настроить Spring для автоматического предоставления этих полей id и методов findById?

2. Используйте отношение к себе

  • Получите собственный URI объекта с angular-hal$href('self') метод
  • Используйте его в качестве параметра страницы и разрешите ресурс, вызвав новый halClient.$get(resourceUri) в теме
  • Недостатки: URI должен обрабатываться до и после размещения в URL страницы, чтобы предотвратить ошибки из-за другого "http://" в адресной строке. Я думал о том, чтобы сделать на нем кодировку base64, но это потребляет много времени.
  • Недостатки: это раскрывает URL-адрес API для всего мира, и эти данные могут быть критическими и должны оставаться скрытыми (даже если они будут доступны через отладчик, следящий за сетевым трафиком).

3. Забудьте о HATEOAS

  • Не беспокойтесь об отношениях и возможности открытия
  • Снимает angular-hal и просто использовать $resource с простыми старыми отображениями URL
  • Недостатки: это идет назад, и кажется, что вы не следуете руководящим принципам...

Итак, я что-то упустил? Какова наилучшая практика в отношении доступа к данным в полной среде RESTFul HATEOAS?

1 ответ

Решение

Я нашел exposeIdsFor методы, позволяющие добавить поле, помеченное @Id в JSON.

@Configuration
public class RepositoryConfiguration  extends SpringBootRepositoryRestMvcConfiguration {

    /**
     * add here the main resources that would need direct access from outside
     */
    @Override
    protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.exposeIdsFor(Contact.class, User.class);
    }
}

Затем я сделал все сущности, которые я хочу, чтобы идентификатор был наследован от общего абстрактного класса.

@MappedSuperclass
public abstract class AbstractEntity {

    @Id @GeneratedValue
    Long id;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
}

этот абстрактный класс обслуживается @NoRepositoryBean хранилище

@NoRepositoryBean
public interface AbstractEntityRepository<T extends AbstractEntity> extends JpaRepository<T, Long> {    
    @RestResource(rel = "byId")
    T findById(@Param("id") Long id);
}

и тогда я могу предоставить и id, и метод byId() для интересующих меня сущностей:

@Entity
public class Contact extends AbstractEntity {

    @Column 
   String name;

    @Column 
    String email;
}

public interface ContactRepository extends AbstractEntityRepository<Contact> {    
}

Я думаю, что это делает хорошую работу вокруг и позволяет прямой доступ организаций от клиента по небольшой цене

Другие вопросы по тегам