java - example - ¿Cómo implementar una aplicación JAX-RS?
web.xml servlet (4)
Como dije en el comentario anterior, todo depende del marco que quiera usar.
http://syrupsucker.blogspot.com/2008/10/deploying-jersey-in-tomcat-60.html para Jersey http://syrupsucker.blogspot.com/2008/10/deploying-resteasy-in-tomcat-60.html para RESTeasy
Por lo que sé, JAX-RS no contiene una especificación para el despliegue.
La especificación JAX-RS 1.1 dice en la página 6:
Si no hay una subclase de Aplicación, el servlet agregado DEBE ser nombrado:
javax.ws.rs.core.Application
¿Cuál es el servlet agregado? ¿Podría ser un servlet arbitrario?
Si una subclase de aplicación está presente y ya hay un servlet definido que tiene un parámetro de inicialización de servlet llamado:
javax.ws.rs.Application
De nuevo, ¿qué es "un servlet" aquí?
Si hay presente una subclase de Aplicación que no está siendo manejada por un servlet existente, entonces el servlet agregado por el ContainerInitializer DEBE ser nombrado con el nombre completo de la subclase Application.
¿El "servlet agregado por el ContainerInitializer" significa que los servlets se agregan automáticamente? ¿Cómo se vería una configuración?
Por el momento no utilizo una clase de aplicación ni un web.xml y funciona (con GlassFish 3.1). ¿Este mecanismo de implementación requiere un escaneo de ruta de clase completa, que podría ser lento con grandes bibliotecas?
¿Cómo implementar en un contenedor Servlet?
Hay un número confuso de opciones de configuración en la web. Vea este ejemplo con parámetros de contexto en el web.xml (¡no funciona para mí!). ¿Cuál es la forma preferida de implementar una aplicación JAX-RS?
Con Servlet3.0, sigue esto. Esto funciona para mí
<servlet>
<description>JAX-RS Tools Generated - Do not modify</description>
<servlet-name>JAX-RS Servlet</servlet-name>
<servlet-class>com.ibm.websphere.jaxrs.server.IBMRestServlet</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>your.restsrv.config.RESTConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<enabled>true</enabled>
<async-supported>false</async-supported>
</servlet>
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>JAX-RS Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Con WAS 8.5, cambio el web.xml para agregar:
<servlet>
<servlet-class>com.ibm.websphere.jaxrs.server.IBMRestServlet</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.tada.rest.RestApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Mi RestApplication se ve así:
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
public class RestApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> sets = new HashSet<Class<?>>();
sets.add(RestService.class);
return sets;
}
}
Mi RestService se parece a
@Path("/tada")
public class RestService {
@GET
public String getSomething() {
return "tada";
}
}
Y añado en el pom.xml la dependencia:
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0</version>
</dependency>
Hay varias opciones para implementar en un contenedor Java EE 6 (más específicamente una implementación de Servlet 3.0):
El más simple es:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_3_0.xsd" version="3.0">
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
Entonces todas las clases @Path
y @Provider
encontradas en su aplicación web estarán disponibles en la aplicación JAX-RS "predeterminada" con un patrón de URL de servlet de "/rest/*"
.
Si tiene una o más clases que extienden javax.ws.rs.core.Application
, puede especificarlo de la siguiente manera:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_3_0.xsd" version="3.0">
<servlet>
<servlet-name>com.example.jaxrs.MyApplication</servlet-name>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>com.example.jaxrs.MyApplication</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
Es posible que desee hacer lo anterior en caso de que solo desee devolver conjuntos específicos de clases @Path
/ @Provider
en una URL (para que pueda tener una segunda MyApplication2 con un patrón de URL diferente más arriba).
También puede omitir todo el web.xml
y simplemente anotar su clase MyApplication
@ApplicationPath
que servirá como patrón de URL. Recomendaría mantener el web.xml
en cualquier caso, ya que probablemente tenga que agregar otra información sobre la aplicación web de todos modos.
Si se pregunta de dónde viene la servlet-class
, el entorno lo agrega automáticamente. Puede hacerse una idea mirando Servlet 3.0 ServletContext
.