Подтвердить что ты не робот

Принятие URI-кода Spring Data REST в пользовательском контроллере

У меня есть приложение Spring Data Rest webmvc, которое я хотел бы добавить для пользовательских функций для пакетных операций.

Я создал контроллер и объединил его в пространство имен uri, но я хотел бы, чтобы он мог принимать URI, как пользовательские запросы /search, а не просто ID.

Я пробовал зарегистрировать собственный конвертер <String, Long> (мой объект имеет тип идентификатора Long, но это кажется проигнорированным. Есть ли способ настроить мой контроллер таким образом, чтобы он принимал это поведение из автоматически реализованного SDR-контроллеры?

Даже если есть какой-то метод, который я могу вызвать, который автоматически разрешит URI для объекта, который будет работать так же хорошо (поскольку я могу просто принять String в моем контроллере)

Здесь, где я нахожусь.

@Configuration
public class CustomWebConfiguration extends WebMvcConfigurationSupport {

    //irrelevant code omitted

    @Bean
    public DomainClassConverter<?> domainClassConverter() {
        DomainClassConverter<FormattingConversionService> dc = new DomainClassConverter<FormattingConversionService>(mvcConversionService());
        return dc;
    }

    @Override
    public void addFormatters(FormatterRegistry registry) {
          registry.addConverter(String.class, Long.class, testConverter());
    }

    @Bean 
    Converter<String, Long> testConverter() {
        return new Converter<String, Long>() {

            @Override
            public Long convert(String source) {
                //this code does _not_ get run at any point
                if (source.indexOf('/') == -1) { return Long.parseLong(source); }

                source = source.substring(source.lastIndexOf('/') + 1);
                Long id = Long.parseLong(source);

                return id;
            }   
        };
    }
}

Конфигурация SDR

@Configuration
@EnableHypermediaSupport(type = { HypermediaType.HAL })
public class CustomRestConfiguration extends RepositoryRestMvcConfiguration {

    @Override
    public RepositoryRestConfiguration config() {
      RepositoryRestConfiguration config = super.config();
      config.setBasePath("/api");
      config.exposeIdsFor(ApplicationMembership.class);
      return config;
    }


}

И мой (надуманный) контроллер:

ApplicationType - это одно из моих объектов, которое правильно управляется магией хранилища SDR/репозитория

@BasePathAwareController
@RepositoryRestController
@RequestMapping("applications/special")
public class ApplicationExtensionController {
    @RequestMapping("a")
    public ResponseEntity<?> reply(@RequestParam("type") ApplicationType type) {
        return new ResponseEntity<String>(type.getIcon(), HttpStatus.OK);
    }
}

Я немного оглянулся, но не могу ничего сделать. Когда я создаю конвертер <String, ApplicationType>, который использует репозиторий, он также не вызывается, поскольку DomainClassConverter просто вызывает свой базовый конвертер <String, Long> (который явно не работает, поскольку он не может правильно разобрать types/1 в длинный.

Цените помощь!

Забыл упомянуть

  • Spring Data Rest 2.4.0
  • Spring HATEOAS 0.19.0
  • Spring 4.2.1

Использование репозиториев JPA

4b9b3361

Ответ 1

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

Мне удалось получить желаемую функциональность, переместив мой testConverter() bean в класс конфигурации расширения RepositoryRestMvcConfiguration, а затем добавив

@Override
public void configureConversionService(ConfigurableConversionService service) {
    service.addConverter(testConverter());
}

И работаем по назначению. Я чувствую себя немного глупо сейчас за то, что выбрал это не в том месте, но, надеюсь, это поможет кому-то другому!

Ответ 2

Я отправляю ответ на основании моего последнего комментария.

По-видимому, требуемая логика - автокодирование URI от @RequestParam до объекта, управляемого репозиторией, - реализована в нескольких частных методах RepositorySearchController (см. executeQueryMethod и prepareUris), поэтому нет простого способ получить его в пользовательских контроллерах.

Вы можете попробовать создать свой собственный преобразователь аргументов с помощью Spring HATEOAS. Посмотрите, как реализуется преобразователь PersistentEntityResourceHandlerMethodArgumentResolver. Он разрешил сущность, основанную на ее @BackendId.