Как правильно зарегистрировать реализации MessageBodyReader и MessageBodyWriter? - PullRequest
0 голосов
/ 15 мая 2018

Я реализовал Javax WS RS API MessageBodyReader для com.ca.tas.crypto.cmp.client.GeneralPKIMessageJaxRsReader и MessageBodyWriter для org.bouncycastle.asn1.cmp.PKIMessage, чтобы можно было легко использовать типы в CMP через HTTP REST API.Теперь, чтобы зарегистрировать типы, я создал файл META-INF/services/javax.ws.rs.ext.Providers и поместил туда имена классов.Все работает нормально, я могу выполнять вызовы REST с помощью API, за исключением:

  • IntelliJ IDEA (или один из установленных в нем плагинов) жалуется, что

    Зарегистрированное расширение должно реализовывать javax.ws.rs.ext.Providers

    в двух строках файла.Основываясь на ресурсах, которые я нашел где-то в Интернете, я подумал, что добавления аннотаций @Provider и @Produces("application/pkixcmp") должно быть достаточно.

  • Я заметил, что в FasterXML Jackson есть META-INF/services/javax.ws.rs.ext.MessageBodyReader и META-INF/services/javax.ws.rs.ext.MessageBodyWriter файлов, и те, кажется, регистрируют класс, который также реализует интерфейсы.

Итак, мои вопросы:

  • Правильно или неправильно IntelliJ IDEA жаловаться на то, что я не внедряю javax.ws.rs.ext.Providers?

  • Какой файл необходим для регистрации реализаций MessageBodyReader и MessageBodyWriter?

  • Какая авторитетная документация могла бы меня проинформировать об этом?

1 Ответ

0 голосов
/ 15 мая 2018

Правильно или неправильно IntelliJ IDEA жаловаться на то, что я не внедряю javax.ws.rs.ext.Providers?

Файлы в META-INF/services являются частью способа, которым мы можем создатьрасширяемые приложения с использованием ServiceLoader.Как это работает, так это то, что имя файла должно быть именем контракта , а содержимое файла должно быть списком реализаций этого контракта.ServiceLoader увидит файл и соберет все реализации.Таким образом, используя ServiceLoader, мы могли бы сделать

ServiceLoader<MessageBodyReader> readersLoader
        = ServiceLoader.load(MessageBodyReader.class);

На основе класса, переданного методу load, Java будет искать файл

META-INF/services/javax.ws.rs.ext.MessageBodyReader

и смотреть насодержимое этого файла, чтобы найти все реализации, которые он должен загрузить.

Таким образом, основываясь на этой информации, вы можете видеть, что IntelliJ является правильным в жалобах, поскольку ваш читатель и писатель не правильнореализовать javax.ws.rs.ext.Providers.

Следует отметить, что я не думаю, что класс ServiceLoader используется напрямую, так как для этого требуется, чтобы реализации службы имели конструкторы без аргументов.Но это именно тот шаблон, который используется в отношении сервисов META.

Каков правильный файл для регистрации реализаций MessageBodyReader и MessageBodyWriter?

Использование META-INF/services файлов не является частью спецификации JAX-RS.Это подробности реализации, которые будут характерны для реализации JAX-RS, хотя этот шаблон часто используется.В основном вы увидите файлы, используемые в библиотеках многократного использования, таких как библиотека Джексона, которую вы упомянули 1 .

Если поставщик будет частью нашего приложения, то есть ещеобщие способы его регистрации.

  • Как вы упомянули, аннотация @Provider является маркерной аннотацией для определения класса провайдера, который должен быть зарегистрирован.Когда сканирование включено, среда выполнения сканирует классы, помеченные @Provider, а затем регистрирует их в приложении.

    Когда мы говорим о сканировании, существует несколько разных способов: сканирование пути к классам и сканирование пакетов.Сканирование пути к классам включается в приложении JAX-RS с помощью пустого класса Application, помеченного @ApplicationPath.

    @ApplicationPath("/api/*")
    public class ApplicationConfig extends Application {}
    

    Этого достаточно, чтобы настроить приложение JAX-RS 2..Будет включено сканирование пути к классам, которое будет сканировать весь путь к классам для всех классов, помеченных @Path и @Provider, и зарегистрировать эти классы.

    Пакет сканирование - это то, что является специфическим дляРеализация джерси.Мы можем настроить наше приложение таким образом:

    @ApplicationPath("api")
    public class ApplicationConfig extends ResourceConfig {
        public ApplicationConfig() {
            package("the.package.to.scan");
        }
    }
    

    Здесь мы говорим Джерси сканировать пакет the.package.to.scan на наличие классов @Path и @Provider для регистрации в приложении.

  • Еще один способ регистрации наших провайдеров - это явная регистрация.В подклассе Application вы должны переопределить getClasses() или getSingletons(), чтобы зарегистрировать их как класс или как объект соответственно.

    @ApplicationPath("/api/*")
    public class ApplicationConfig extends Application {
        private final Set<Class<?>> classes = new HashSet<>();
        private final Set<Object> singletons = new HashSet<>();
    
        public ApplicationConfig() {
            classes.add(MyMessageBodyReader.class);
            singletons.add(new MyMessageBodyReader());
        }
    
        @Override
        public Set<Class<?>> getClasses() {
            return this.classes;
        }
    
        @Override
        public Set<Object> getSingletons() {
            return this.singletons;
        }
    }
    

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

    Если вы используете реализацию на Джерси, существуют также специфические для Джерси способы, с помощью которых мы можем явно регистрировать ресурсы и поставщиков.Подробнее об этом см. Что такое класс ResourceConfig на Джерси 2? .

  • Еще один способ регистрации поставщиков заключается в использовании функций.,Мы можем использовать ваниль Feature или DynamicFeature.

    . С помощью Feature мы регистрируем провайдера со всем приложением

    // We should register the feature with our application
    public class MyFeature implements Feature {
        @Override
        public boolean configure(FeatureContext context) {
             context.register(MyMessageBodyReader.class);
        }
    }
    

    С помощью DynamicFeature мы можем выборочно зарегистрировать провайдера с конкретными методами или классами ресурсов.Подробнее о документах в Джерси о динамическом связывании .Следует отметить, что динамическое связывание больше используется с фильтрами и перехватчиками (которые также в общем смысле термина «поставщики»), а не с поставщиками объектов (MessageBodyReader / Writers).

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

Что такоеавторитетная документация, которая могла бы проинформировать меня об этом?

Я не уверен, сколько информации о файлах META-INF / service в какой-либо документации.Но явную регистрацию и сканирование пути к классам вы, вероятно, найдете в спецификации JAX-RS или Документация Джерси


1 - это следует отметитьто, что файл есть, не означает, что он будет использован.Это зависит от реализации JAX-RS, хотят ли они его использовать.Например, Джерси не будет использовать его на MessageBodyReader s и устройствах записи.

2 - См. Как использовать Джерси в качестве реализации JAX-RS без web.xml?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...