Что такое класс 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):

  1. Только с web.xml
  2. Как с web.xml, так и с Application/ResourceConfig учебный класс
  3. Только с 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-paramjavax.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-paramparam-name , Если вы используете конфигурацию Java ( ResourceConfig ), тогда вы бы позвонили property(ServerProperties.SOME_CONF, value)

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