¿Qué es exactamente la clase ResourceConfig en Jersey 2?


He visto muchos tutoriales de Jersey que comienzan con algo como

@ApplicationPath("services")
public class JerseyApplication extends ResourceConfig {
    public JerseyApplication() {
        packages("com.abc.jersey.services");
    }
}

Sin explicar qué es exactamente la clase ResourceConfig. Entonces, ¿dónde puedo encontrar su documentación, uso, etc.? Buscar en Google "jersey resourceconfig" no produce ningún documento oficial.

Algunas de mis preguntas sobre esta clase y su uso son:

  • ¿Qué cosas puedo hacer dentro de la subclase de ResourceConfig?
  • Necesito registrar la subclase de ResourceConfig en algún lugar para que pueda ser encontrado o es detectado automáticamente por Jersey?
  • Si la subclase se detecta automáticamente ¿qué sucede si tengo múltiples subclases de ResourceConfig?
  • ¿Es el propósito de ResourceConfig el mismo que el archivo web.xml? Si es así, ¿qué sucede si tengo ambos en mi proyecto? ¿Una de ellas tiene prioridad sobre la otra?
Author: Chin, 2017-08-11

1 answers

El estándar JAX-RS utiliza un Application como su clase de configuración. ResourceConfig extiende Application.

Hay tres formas principales diferentes (en un contenedor servlet) para configurar Jersey (JAX-RS):

  1. Con solo web.xml
  2. Con ambas web.xml y una clase Application/ResourceConfig
  3. Con solo una clase Application/ResourceConfig anotada con @ApplicationPath.

Con solo web.xml

Es posible configurar la aplicación en un estándar JAX-RS way, pero lo siguiente es específico de Jersey

<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>

Dado que Jersey se ejecuta en un contenedor de servlet, es correcto que la aplicación Jersey se ejecute como un servlet. El servlet de Jersey que maneja las solicitudes entrantes es el ServletContainer. Así que aquí configuramos su servlet. También configuramos un init-param para Jersey para saber qué paquete(s) escanear para nuestras clases @Path y @Provider para que pueda registrarlas,

Bajo el capó, Jersey realmente creará un ResourceConfig, ya que eso es lo que usa para configurar la aplicación. Luego registrará todas las clases que descubra a través del escaneo del paquete.

Con ambas web.xml y Application/ResourceConfig

Podemos usar la web anterior.xml, pero en lugar de configurar un init-param para buscar paquetes, usamos un init-param para declarar un Application/ResourceConfig que usaremos para configurar programáticamente nuestra aplicación.

<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");
    }
}

Aquí, configuramos el init-param javax.ws.rs.Application con el nombre completo de nuestra subclase ResourceConfig. Y en vez de usando el init-param que le dice a Jersey qué paquete(s) escanear, solo usamos el método de conveniencia packages() del ResourceConfig.

También podríamos usar los métodos register() y property() para registrar recursos y proveedores, y para configurar propiedades de Jersey. Con el método property(), cualquier cosa que se pueda configurar como init-param, también se puede configurar usando el método property(). Por ejemplo, en lugar de llamar packages(), podríamos hacer

public JerseyApplication() {
    property("jersey.config.server.provider.packages",
             "com.mypackage.to.scan");
}

Con solo Application/ResourceConfig

Sin una red.xml, Jersey necesita una forma para nosotros de proporcionar el servlet-mapping. Hacemos esto con la anotación @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");
    }
}

Aquí con el @ApplicationPath, es como si configuráramos el mapeo de servlet en la web.xml

<servlet-mapping>
    <servlet-name>JerseyApplication</servlet-name>
    <url-pattern>/services/*</url-pattern>
</servlet-mapping>

Cuando se utiliza solo código Java para la configuración, tiene que haber alguna forma de que Jersey descubra nuestra clase de configuración. Esto se hace con el uso de un ServletContanerInitializer. Esto es algo que se introdujo en la especificación Servlet 3.0, por lo que no podemos usar " solo Java" configuración en contenedores servlet anteriores.

Básicamente lo que sucede es que el implementador del inicializador puede decirle al contenedor servlet qué clases buscar, y el contenedor servlet pasará esas clases al método inicializador onStartup(). En la implementación de Jersey del inicializador, Jersey lo configura para buscar Application clases y clases anotadas con @ApplicationPath. Ver este post para mayor explicación. Tan cuando el envase del servlet comienza aplicación, inicializador de Jersey se pasará nuestra clase Application/ResourceConfig.

Qué cosas puedo hacer dentro de la subclase de ResourceConfig

Basta con mirar el javadoc. Su mayoría solo registro de clases. No hay mucho más que tengas que hacer con él. Los principales métodos que utilizará son los siguientes:register(), packages(), y property() métodos. El método register() le permite registrar manualmente clases e instancias de recursos y proveedores. El método packages(), discutido anteriormente, enumera los paquetes que desea que Jersey escanee para las clases @Path y @Provider y los registre por usted. Y el método property() le permite establecer algunas propiedades configurables 1.

El ResourceConfig es solo una clase de conveniencia. Recuerde, se extiende Application, por lo que incluso podríamos usar la clase estándar 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;
    }
}

Con un ResourceConfig, simplemente haríamos{[65]]}

public class JerseyApplication extends ResourceConfig {
    public JerseyApplication() {
        register(MyResource.class);
        register(new MyProvider());
        packages("com.mypackages.to.scan");
    }
}

Además de ser más conveniente, también hay algunas cosas debajo del capó que ayudan a Jersey a configurar el aplicación.


Notas al pie

1. Hay una serie de propiedades configurables diferentes. El enlace a la ServerProperties son solo algunas propiedades generales. También hay diferentes propiedades relacionadas con características específicas. La documentación debe mencionar estas propiedades en la sección de los documentos relacionados con esa característica. Para obtener una lista completa de todas las propiedades configurables de, puede mirar todas las constantes de Jersey y buscar aquellos donde el valor de la cadena comienza con jersey.config. Si estás usando una web.xml, a continuación, se utilizaría el valor de cadena como el init-param param-name. Si está utilizando Java config (ResourceConfig), entonces llamaría property(ServerProperties.SOME_CONF, value)

 63
Author: Paul Samsotha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-05 03:30:14