Правильно или неправильно 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?