java 如何使用 CXF、JAX-RS 和 HTTP 缓存

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2085411/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 19:21:43  来源:igfitidea点击:

How to use CXF, JAX-RS and HTTP Caching

javarestcxfjax-rshttp-caching

提问by sfussenegger

The CXFdocumentation mentions caching as Advanced HTTP:

CXF文档中提到缓存为高级HTTP

CXF JAXRS provides support for a number of advanced HTTP features by handling If-Match, If-Modified-Since and ETags headers. JAXRS Request context object can be used to check the preconditions. Vary, CacheControl, Cookies and Set-Cookies are also supported.

CXF JAXRS 通过处理 If-Match、If-Modified-Since 和 ETags 标头,为许多高级 HTTP 功能提供支持。JAXRS 请求上下文对象可用于检查前提条件。还支持 Vary、CacheControl、Cookies 和 Set-Cookies。

I'm really interested in using (or at least exploring) these features. However, while "provides support" sounds really interesting, it isn't particularly helpful in implementing such features. Any help or pointers on how to use If-Modified-Since, CacheControl or ETags?

我对使用(或至少探索)这些功能非常感兴趣。然而,虽然“提供支持”听起来很有趣,但它在实现这些功能方面并不是特别有帮助。关于如何使用 If-Modified-Since、CacheControl 或 ETags 的任何帮助或指示?

回答by sfussenegger

Actually, the answer isn't specific to CXF - it's pure JAX-RS:

实际上,答案并非特定于 CXF - 它是纯粹的 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();
}

回答by Jan Algermissen

With the forthcoming JAX-RS 2.0 it will be possible to apply Cache-Control declaratively, as explained in http://jalg.net/2012/09/declarative-cache-control-with-jax-rs-2-0/

随着即将推出的 JAX-RS 2.0,可以声明性地应用 Cache-Control,如http://jalg.net/2012/09/declarative-cache-control-with-jax-rs-2-0/ 中所述

You can already test this at least with Jersey. Not sure about CXF and RESTEasy though.

您至少可以使用 Jersey 进行测试。虽然不确定 CXF 和 RESTEasy。

回答by loicmathieu

CXF didn't implements dynamic filtering as explained here : http://www.jalg.net/2012/09/declarative-cache-control-with-jax-rs-2-0

CXF 没有按照此处的说明实现动态过滤:http: //www.jalg.net/2012/09/declarative-cache-control-with-jax-rs-2-0

And if you use to return directly your own objects and not CXF Response, it's hard to add a cache control header.

如果你习惯直接返回你自己的对象而不是 CXF 响应,那么很难添加缓存控制头。

I find an elegant way by using a custom annotation and creating a CXF Interceptor that read this annotation and add the header.

我找到了一种优雅的方法,即使用自定义注释并创建一个读取此注释并添加标题的 CXF 拦截器。

So first, create a CacheControl annotation

所以首先,创建一个CacheControl注解

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

Then, add this annotation to your CXF operation method (interface or implementation it works on both if you use an interface)

然后,将此注释添加到您的 CXF 操作方法中(如果您使用接口,则它适用于两者的接口或实现)

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

Then create a CacheControl interceptor that will handle the annotation and add the header to your response.

然后创建一个 CacheControl 拦截器,它将处理注释并将标头添加到您的响应中。

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

Finally configure CXF to use your interceptor, you can find all the needed information here : http://cxf.apache.org/docs/interceptors.html

最后配置 CXF 以使用您的拦截器,您可以在这里找到所有需要的信息:http: //cxf.apache.org/docs/interceptors.html

Hope it will help.

希望它会有所帮助。

Lo?c

位置