jaxrs jax consume clients java rest cxf jax-rs http-caching

java - consume - Cómo usar CXF, JAX-RS y HTTP Caching



jax rs consume rest service (3)

CXF no implementó el filtrado dinámico como se explica aquí: http://www.jalg.net/2012/09/declarative-cache-control-with-jax-rs-2-0

Y si utiliza para devolver directamente sus propios objetos y no CXF Response, es difícil agregar un encabezado de control de caché.

Encuentro una forma elegante utilizando una anotación personalizada y creando un Interceptor CXF que lee esta anotación y agrega el encabezado.

Así que primero, crea una anotación CacheControl

@Target(ElementType.METHOD ) @Retention(RetentionPolicy.RUNTIME) public @interface CacheControl { String value() default "no-cache"; }

Luego, agregue esta anotación a su método de operación CXF (interfaz o implementación funciona en ambos si usa una interfaz)

@CacheControl("max-age=600") public Person getPerson(String name) { return personService.getPerson(name); }

Luego cree un interceptor CacheControl que manejará la anotación y agregará el encabezado a su respuesta.

public class CacheInterceptor extends AbstractOutDatabindingInterceptor{ public CacheInterceptor() { super(Phase.MARSHAL); } @Override public void handleMessage(Message outMessage) throws Fault { //search for a CacheControl annotation on the operation OperationResourceInfo resourceInfo = outMessage.getExchange().get(OperationResourceInfo.class); CacheControl cacheControl = null; for (Annotation annot : resourceInfo.getOutAnnotations()) { if(annot instanceof CacheControl) { cacheControl = (CacheControl) annot; break; } } //fast path for no cache control if(cacheControl == null) { return; } //search for existing headers or create new ones Map<String, List<String>> headers = (Map<String, List<String>>) outMessage.get(Message.PROTOCOL_HEADERS); if (headers == null) { headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); outMessage.put(Message.PROTOCOL_HEADERS, headers); } //add Cache-Control header headers.put("Cache-Control", Collections.singletonList(cacheControl.value())); } }

Finalmente, configure CXF para usar su interceptor, puede encontrar toda la información necesaria aquí: http://cxf.apache.org/docs/interceptors.html

Espero que ayude.

Loïc

La documentación de CXF menciona el almacenamiento en caché como HTTP avanzado :

CXF JAXRS brinda soporte para una serie de funciones HTTP avanzadas al manejar los encabezados If-Match, If-Modified-Since y ETags. El objeto de contexto JAXRS Request se puede usar para verificar las condiciones previas. Vary, CacheControl, Cookies y Set-Cookies también son compatibles.

Estoy realmente interesado en usar (o al menos explorar) estas funciones. Sin embargo, aunque "proporciona soporte" suena realmente interesante, no es particularmente útil para implementar tales funciones. ¿Alguna ayuda o consejos sobre cómo usar If-Modified-Since, CacheControl o ETags?



En realidad, la respuesta no es específica de CXF, es pura JAX-RS:

// IPersonService.java import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.Request; import javax.ws.rs.core.Response; @GET @Path("/person/{id}") Response getPerson(@PathParam("id") String id, @Context Request request); // PersonServiceImpl.java import javax.ws.rs.core.CacheControl; import javax.ws.rs.core.EntityTag; import javax.ws.rs.core.Request; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; public Response getPerson(String name, Request request) { Person person = _dao.getPerson(name); if (person == null) { return Response.noContent().build(); } EntityTag eTag = new EntityTag(person.getUUID() + "-" + person.getVersion()); CacheControl cc = new CacheControl(); cc.setMaxAge(600); ResponseBuilder builder = request.evaluatePreconditions(person.getUpdated(), eTag); if (builder == null) { builder = Response.ok(person); } return builder.cacheControl(cc).lastModified(person.getUpdated()).build(); }