Что такое класс ResourceConfig в Джерси 2?
Я видел много уроков по Джерси, которые начинаются с чего-то вроде
@ApplicationPath("services")
public class JerseyApplication extends ResourceConfig {
public JerseyApplication() {
packages("com.abc.jersey.services");
}
}
не объясняя, что именно ResourceConfig
класс есть. Так, где я могу найти его документацию, использование и т. Д.? Поиск в Google для "jersey resourceconfig" не дает никакого официального документа.
Некоторые из моих вопросов об этом классе и его использовании:
- Что я могу сделать внутри подкласса
ResourceConfig
? - Нужно ли регистрировать подкласс
ResourceConfig
где-нибудь, чтобы его можно было найти или он автоматически обнаруживается Джерси? - Если подкласс автоматически определяется, что произойдет, если у меня есть несколько подклассов
ResourceConfig
? - Является ли целью
ResourceConfig
так же, какweb.xml
файл? Если так, что произойдет, если у меня есть оба в моем проекте? Один из них имеет приоритет над другим?
1 ответ
Стандарт JAX-RS использует Application
как его класс конфигурации. ResourceConfig
продолжается Application
,
Существует три основных способа (в контейнере сервлетов) настроить Джерси (JAX-RS):
- Только с web.xml
- Как с web.xml, так и с
Application/ResourceConfig
учебный класс - Только с
Application/ResourceConfig
класс с пометкой@ApplicationPath
,
Только с web.xml
Можно настроить приложение стандартным способом JAX-RS, но следующее характерно для Джерси
<web-app>
<servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.mypackage.to.scan</param-value>
</init-param>
</servlet>
...
<servlet-mapping>
<servlet-name>jersey-servlet</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
...
</web-app>
Поскольку Jersey запускается в контейнере сервлетов, то совершенно верно, что приложение Jersey работает как сервлет. Сервлет Джерси, который обрабатывает входящие запросы, является ServletContainer
, Итак, здесь мы объявляем это как <servlet-class>
, Мы также настраиваем <init-param>
сообщая Джерси, какой пакет (ы) сканировать для нашего @Path
а также @Provider
классы, чтобы он мог их зарегистрировать.
Под капотом Джерси на самом деле создаст ResourceConfig
Например, это то, что он использует для настройки приложения. Затем он зарегистрирует все классы, обнаруженные при сканировании пакета.
С обоими web.xml и Application/ResourceConfig
Если мы хотим программно настроить наше приложение с Application
или же ResourceConfig
подкласс, мы можем сделать это с одним изменением вышеупомянутого web.xml. Вместо того, чтобы устанавливать init-param для сканирования пакетов, мы используем init-param для объявления нашего Application/ResourceConfig
подкласс.
<servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.example.JerseyApplication</param-value>
</init-param>
<servlet-mapping>
<servlet-name>jersey-servlet</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
</servlet>
package com.example;
public class JerseyApplication extends ResourceConfig {
public JerseyApplication() {
packages("com.abc.jersey.services");
}
}
Здесь мы настраиваем init-param
javax.ws.rs.Application
с полным именем нашего ResourceConfig
подкласс. И вместо того, чтобы использовать init-param
который сообщает Джерси, какой пакет (ы) сканировать, мы просто используем удобный метод packages()
из ResourceConfig
,
Мы могли бы также использовать методы register()
а также property()
для регистрации ресурсов и поставщиков, а также для настройки свойств Джерси. С property()
метод, все, что может быть настроено как init-param
также можно настроить с помощью property()
метод. Например, вместо того, чтобы звонить packages()
мы могли бы сделать
public JerseyApplication() {
property("jersey.config.server.provider.packages",
"com.mypackage.to.scan");
}
Только с Application/ResourceConfig
Без web.xml Джерси нужен способ предоставить нам отображение сервлетов. Мы делаем это с @ApplicationPath
аннотаций.
// 'services', '/services', or '/services/*'
// is all the same. Jersey will change it to be '/services/*'
@ApplicationPath("services")
public class JerseyApplication extends ResourceConfig {
public JerseyApplication() {
packages("com.abc.jersey.services");
}
}
Здесь с @ApplicationPath
это так же, как если бы мы настроили отображение сервлета в web.xml
<servlet-mapping>
<servlet-name>JerseyApplication</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
При использовании только Java-кода для конфигурации у Джерси должен быть какой-то способ обнаружить наш класс конфигурации. Это делается с использованием ServletContanerInitializer
, Это то, что было представлено в спецификации Servlet 3.0, поэтому мы не можем использовать конфигурацию "только Java" в более ранних контейнерах сервлетов.
В основном происходит то, что разработчик инициализатора может сообщить контейнеру сервлета, какие классы искать, и контейнер сервлета передаст эти классы инициализатору. onStartup()
метод. В реализации инициализатора Джерси Джерси настраивает его на поиск Application
классы и классы с пометкой @ApplicationPath
, Смотрите этот пост для дальнейшего объяснения. Поэтому, когда сервлет-контейнер запускает приложение, инициализатор Джерси будет передан нашему Application/ResourceConfig
учебный класс.
Что я могу сделать внутри подкласса ResourceConfig
Просто посмотрите на Javadoc. В основном это просто регистрация классов. Не так много, что вам нужно сделать с этим. Основными методами, которые вы будете использовать, являются register()
, packages()
, а также property()
методы. register()
Метод позволяет вручную регистрировать классы и экземпляры ресурсов и поставщиков. packages()
метод, рассмотренный ранее, перечисляет пакеты, которые вы хотите, чтобы Джерси сканировал @Path
а также @Provider
классы и зарегистрировать их для вас. И property()
Метод позволяет установить некоторые настраиваемые свойства 1.
ResourceConfig
это просто удобный класс. Помните, это расширяет Application
чтобы мы могли использовать стандарт Application
учебный класс
@ApplicationPath("/services")
public class JerseyApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
final Set<Class<?>> classes = new HashSet<>();
classes.add(MyResource.class);
return classes;
}
@Override
public Set<Object> getSingletons() {
final Set<Object> singletons = new HashSet<>();
singletons.add(new MyProvider());
return singletons;
}
@Override
public Map<String, Object> getProperties() {
final Map<String, Object> properties = new HashMap<>();
properties.put("jersey.config.server.provider.packages",
"com.mypackage.to.scan");
return properties;
}
}
С ResourceConfig
мы бы просто сделали
public class JerseyApplication extends ResourceConfig {
public JerseyApplication() {
register(MyResource.class);
register(new MyProvider());
packages("com.mypackages.to.scan");
}
}
Помимо удобства, есть еще несколько вещей, которые помогают Джерси настроить приложение.
Экологическая среда
Все приведенные выше примеры предполагают, что вы работаете в установленной серверной среде, например Tomcat. Но вы также можете запустить приложение в среде SE, где вы запускаете встроенный сервер и запускаете приложение из main
метод. Иногда вы будете видеть эти примеры при поиске информации, поэтому я хочу показать, как это выглядит, так что, когда вы все сталкиваетесь с этим, вы не удивляетесь и не знаете, как она отличается от ваших настроек.
Так что иногда вы увидите пример, как
ResourceConfig config = new ResourceConfig();
config.packages("com.my.package");
config.register(SomeFeature.class);
config.property(SOME_PROP, someValue);
Скорее всего, здесь происходит то, что в примере используется встроенный сервер, такой как Grizzly. Остальная часть кода для запуска сервера может быть что-то вроде
public static void main(String[] args) {
ResourceConfig config = new ResourceConfig();
config.packages("com.my.package");
config.register(SomeFeature.class);
config.property(SOME_PROP, someValue);
String baseUri = "http://localhost:8080/api/";
HttpServer server = GrizzlyHttpServerFactory
.createHttpServer(URI.create(baseUri), config);
server.start();
}
Таким образом, в этом примере запускается автономный сервер и ResourceConfig
используется для настройки Джерси Здесь и от предыдущих примеров отличается то, что в этом примере мы не расширяем ResourceConfig
Но вместо этого просто создаю его экземпляр. Ничего не изменилось бы, если бы мы
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
packages("com.my.package");
register(SomeFeature.class);
property(SOME_PROP, someValue);
}
}
HttpServer server = GrizzlyHttpServerFactory
.createHttpServer(URI.create(baseUri), new JerseyConfig());
Скажем, вы проходили какое-то учебное пособие, и оно показало конфигурацию для автономного приложения, в котором они ResourceConfig
, но вы запускаете свое приложение в контейнере сервлета и используете более раннюю конфигурацию, в которой вы расширяете ResourceConfig
, Ну, теперь вы знаете, в чем разница и какие изменения вам нужно внести. Я видел людей, делающих действительно странные вещи, потому что они не понимали эту разницу. Например, я видел, как кто-то ResourceConfig
внутри класса ресурсов. Вот почему я добавил этот маленький кусочек; так что вы не делаете ту же ошибку.
Сноски
1. Существует ряд различных настраиваемых свойств. Ссылка на ServerProperties
только некоторые общие свойства. Есть также различные свойства, связанные с конкретными функциями. В документации должны быть упомянуты эти свойства в разделе документации, относящейся к этой функции. Для получения полного списка всех настраиваемых свойств вы можете посмотреть на все константы Джерси и найти те, с которых начинается строковое значение jersey.config
, Если вы используете web.xml, вы должны использовать строковое значение в качестве init-param
param-name
, Если вы используете конфигурацию Java ( ResourceConfig
), тогда вы бы позвонили property(ServerProperties.SOME_CONF, value)