java - que - no guardar cache html5
Jersey: control de caché predeterminado para no-caché (5)
Creo que puedes usar el
isNoCache(true)
que detendrá el almacenamiento en caché en el navegador.
Ver:
http://jersey.java.net/nonav/apidocs/1.12/jersey/javax/ws/rs/core/CacheControl.html#isNoCache%28%29
Espero que esto ayude.
Mientras escribo un servicio web RESTful, me encuentro con problemas si habilito cualquier tipo de almacenamiento en caché en mi cliente (actualmente un cliente grueso .NET). De forma predeterminada, Jersey no está enviando ningún tipo de encabezado de control de caché, por lo que el cliente almacena en caché la mayoría de las páginas automáticamente (lo que parece ser un comportamiento válido).
Me gustaría que Jersey envíe de forma predeterminada un control de caché de "no-caché" y luego, en determinadas respuestas, anule el control de caché.
¿Hay alguna manera de hacer esto con Jersey?
Descubrí que RESTeasy tiene la capacidad de usar la anotación @NoCache para especificar la configuración de toda la clase, pero no he encontrado nada similar con Jersey.
Esto es fácil con Jersey usando ResourceFilterFactory: puede crear cualquier anotación personalizada que adjunte a sus métodos para establecer la configuración del control de caché. Se llama a ResourceFilterFactories para cada método de recurso descubierto cuando la aplicación se inicializa; en ResourceFilterFactory puede verificar si el método tiene su anotación @CacheControlHeader (o lo que quiera llamar); si no, simplemente devuelva el filtro de respuesta que agrega "no-cache" "directiva a la respuesta, de lo contrario, debe utilizar la configuración de la anotación. Aquí hay un ejemplo de cómo hacer eso:
public class CacheFilterFactory implements ResourceFilterFactory {
private static final List<ResourceFilter> NO_CACHE_FILTER = Collections.<ResourceFilter>singletonList(new CacheResponseFilter("no-cache"));
@Override
public List<ResourceFilter> create(AbstractMethod am) {
CacheControlHeader cch = am.getAnnotation(CacheControlHeader.class);
if (cch == null) {
return NO_CACHE_FILTER;
} else {
return Collections.<ResourceFilter>singletonList(new CacheResponseFilter(cch.value()));
}
}
private static class CacheResponseFilter implements ResourceFilter, ContainerResponseFilter {
private final String headerValue;
CacheResponseFilter(String headerValue) {
this.headerValue = headerValue;
}
@Override
public ContainerRequestFilter getRequestFilter() {
return null;
}
@Override
public ContainerResponseFilter getResponseFilter() {
return this;
}
@Override
public ContainerResponse filter(ContainerRequest request, ContainerResponse response) {
// attache Cache Control header to each response based on the annotation value
response.getHttpHeaders().putSingle(HttpHeaders.CACHE_CONTROL, headerValue);
return response;
}
}
}
La anotación puede verse así:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CacheControlHeader {
String value();
}
ResourceFilterFactory se puede registrar en su aplicación agregando el siguiente param inicial a la definición de servlet de Jersey en web.xml:
<init-param>
<param-name>com.sun.jersey.spi.container.ResourceFilters</param-name>
<param-value>package.name.CacheFilterFactory</param-value>
</init-param>
Basado en la solución de @ martin-matula, creé dos anotaciones de caché. One @NoCache
para ningún almacenamiento en caché y un @CacheMaxAge
para almacenamiento en caché específico. CacheMaxAge
toma dos argumentos para que usted no tenga que calcular los segundos usted mismo:
@GET
@CacheMaxAge(time = 10, unit = TimeUnit.MINUTES)
@Path("/awesome")
public String returnSomethingAwesome() {
...
}
El ResourceFilter ahora tiene este método de creación que por defecto no interfiere (para que otros mecanismos de caché sigan funcionando):
@Override
public List<ResourceFilter> create(AbstractMethod am) {
if (am.isAnnotationPresent(CacheMaxAge.class)) {
CacheMaxAge maxAge = am.getAnnotation(CacheMaxAge.class);
return newCacheFilter("max-age: " + maxAge.unit().toSeconds(maxAge.time()));
} else if (am.isAnnotationPresent(NoCache.class)) {
return newCacheFilter("no-cache");
} else {
return Collections.emptyList();
}
}
private List<ResourceFilter> newCacheFilter(String content) {
return Collections
.<ResourceFilter> singletonList(new CacheResponseFilter(content));
}
Puedes ver la solución completa en mi blog .
Gracias por la solución Martin!
Encontré una anotación que puede desactivar el almacenamiento en caché. Puedes usar la siguiente anotación para tu API:
@CacheControl(noCache = true)
La solución de @martin-matula no funciona con JAX-RS 2.0 / Jersey 2.x ya que ResourceFilterFactory y ResourceFilter han sido eliminados. La solución se puede adaptar a JAX-RS 2.0 de la siguiente manera.
Anotación:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CacheControlHeader {
String value();
}
DynamicFeature:
@Provider
public class CacheFilterFactory implements DynamicFeature {
private static final CacheResponseFilter NO_CACHE_FILTER =
new CacheResponseFilter("no-cache");
@Override
public void configure(ResourceInfo resourceInfo,
FeatureContext featureContext) {
CacheControlHeader cch = resourceInfo.getResourceMethod()
.getAnnotation(CacheControlHeader.class);
if (cch == null) {
featureContext.register(NO_CACHE_FILTER);
} else {
featureContext.register(new CacheResponseFilter(cch.value()));
}
}
private static class CacheResponseFilter implements ContainerResponseFilter {
private final String headerValue;
CacheResponseFilter(String headerValue) {
this.headerValue = headerValue;
}
@Override
public void filter(ContainerRequestContext containerRequestContext,
ContainerResponseContext containerResponseContext) {
// attache Cache Control header to each response
// based on the annotation value
containerResponseContext
.getHeaders()
.putSingle(HttpHeaders.CACHE_CONTROL, headerValue);
}
}
}
CacheFilterFactory necesita estar registrado con Jersey. Lo estoy haciendo a través de Dropwizard - usando environment.jersey (). Register () - pero en sistemas independientes entiendo que esto se puede hacer, por ejemplo, dejando que Jersey escanee tus clases para anotaciones de @Provider definiendo lo siguiente en tu web.xml :
<servlet>
<servlet-name>my.package.MyApplication</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<!-- Register resources and providers under my.package. -->
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>my.package</param-value>
</init-param>
</servlet>
Consulte esta publicación para obtener más información sobre el registro de componentes.