Как я могу исключить контроллер Spring Data REST из сгенерированной документации OpenAPI

Я работаю с проектом Spring Data MongoDB, который экспортирует свои конечные точки через Spring Data REST. Он использует модуль springdoc-openapi-data-rest библиотеки springdoc-openapi для создания описания интерфейса OpenAPI для конечных точек Spring Data REST в проекте.

У меня есть конечная точка репозитория, которую я хотел бы исключить из сгенерированного документа OpenAPI.

@Repository
public interface ExcludeMeRepository extends
        PagingAndSortingRepository<ExcludeMe, Integer> {}

Если бы это был контроллер Spring MVC, подключаемый через springdoc-openapi-ui, я мог бы использовать аннотацию @Hidden из библиотеки аннотаций Swagger на контроллере. Однако это, похоже, не работает, когда надевается на класс @Repository.

@Hidden // Does not appear to have an effect
@Repository
public interface ExcludeMeRepository extends
        PagingAndSortingRepository<ExcludeMe, Integer> {}

Я попробовал несколько вещей, но не нашел ничего, что работало бы, кроме того, что это было похоже на хакерский обходной путь.

Как можно исключить репозиторий из сгенерированного документа OpenAPI?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
233
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Это больше относится к категории «хакерских обходных путей», но я обнаружил, что использование настроенного bean-компонента SpringRepositoryRestResourceProvider , который явно исключает данный тип сущности, работает. Определение его как bean-компонента переопределяет значение по умолчанию в SpringDocDataRestConfiguration.

@Configuration
public class OpenApiConfig {
    @Bean
    public SpringRepositoryRestResourceProvider springRepositoryRestResourceProvider(
            ResourceMappings mappings, ListableBeanFactory listableBeanFactory,
            Associations associations, ApplicationContext applicationContext, 
            DataRestRouterOperationService dataRestRouterOperationService,
            PersistentEntities persistentEntities, ObjectMapper mapper, 
            SpringDocDataRestUtils springDocDataRestUtils) {
        Repositories filteredRepositories = 
                new RepositoriesWithoutExcludeMe(listableBeanFactory);

        return new SpringRepositoryRestResourceProvider(
                mappings, filteredRepositories, associations, 
                applicationContext, dataRestRouterOperationService, 
                persistentEntities, mapper, springDocDataRestUtils);
    }

    private static class RepositoriesWithoutExcludeMe extends Repositories {
        RepositoriesWithoutExcludeMe(ListableBeanFactory factory) {
            super(factory);
        }

        @Override
        public boolean hasRepositoryFor(Class<?> domainClass) {
            return !isExcludeMe(domainClass) 
                   && super.hasRepositoryFor(domainClass);
        }

        @Override
        public Optional<Object> getRepositoryFor(Class<?> domainClass) {
            return optional(domainClass, super::getRepositoryFor);
        }

        @Override
        public <T, S> EntityInformation<T, S> getEntityInformationFor(
                Class<?> domainClass) {
            return nullable(domainClass, super::getEntityInformationFor);
        }

        @Override
        public Optional<RepositoryInformation> getRepositoryInformationFor(
                Class<?> domainClass) {
            return optional(domainClass, super::getRepositoryInformationFor);
        }

        @Override
        public RepositoryInformation getRequiredRepositoryInformation(
                Class<?> domainType) {
            if (isExcludeMe(domainType)) {
                throw new IllegalArgumentException(
                        "No required RepositoryInformation found for domain type " 
                        + domainType.getName());
            } else {
                return nullable(domainType, 
                        super::getRequiredRepositoryInformation);
            }
        }

        @Override
        public Optional<RepositoryInformation> getRepositoryInformation(
                Class<?> repositoryInterface) {
            return optional(repositoryInterface, 
                    super::getRepositoryInformation);
        }

        @Override
        public PersistentEntity<?, ?> getPersistentEntity(
                Class<?> domainClass) {
            return nullable(domainClass, super::getPersistentEntity);
        }

        @Override
        public List<QueryMethod> getQueryMethodsFor(Class<?> domainClass) {
            return isExcludeMe(domainClass) 
                    ? List.of() : super.getQueryMethodsFor(domainClass);
        }

        @Override
        public Iterator<Class<?>> iterator() {
            return Iterators.filter(super.iterator(), c -> !isExcludeMe(c));
        }

        private static boolean isExcludeMe(Class<?> domainClass) {
            return ExcludeMe.class.isAssignableFrom(domainClass);
        }

        private <C extends Class<?>, R> Optional<R> optional(
                C domainClass, Function<C, Optional<R>> function) {
            return isExcludeMe(domainClass) 
                    ? Optional.empty() : function.apply(domainClass);
        }

        private <C extends Class<?>, R> R nullable(
                C domainClass, Function<C, R> function) {
            return isExcludeMe(domainClass) 
                    ? null : function.apply(domainClass);
        }
    }
}

Возможно @RepositoryRestResource(exported = false) это то, что вы ищете. Для вашего примера это будет выглядеть следующим образом:

@Repository
@RepositoryRestResource(exported = false)
public interface ExcludeMeRepository extends
        PagingAndSortingRepository<ExcludeMe, Integer> {}

См. Справочное руководство Spring Data REST — Скрытие определенных репозиториев, методов запросов или полей

Это решение делает ресурс недоступным через REST. Это не соответствует моей потребности, так как я все еще хочу, чтобы репозиторий был доступен через REST; Я просто не хочу, чтобы он отображался в документе OpenAPI, созданном приложением.

M. Justin 09.11.2022 17:34
Ответ принят как подходящий

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