代码之家  ›  专栏  ›  技术社区  ›  sfussenegger

如何使用cxf、jax-rs和http缓存

  •  17
  • sfussenegger  · 技术社区  · 15 年前

    这个 CXF 文档提到缓存为 Advanced HTTP :

    cxf jaxrs通过处理if-match、if-modified-since和etags头来支持许多高级HTTP功能。JAXRS请求上下文对象可用于检查前提条件。还支持vary、cachecontrol、cookies和set cookies。

    我对使用(或者至少是探索)这些特性很感兴趣。然而,尽管“提供支持”听起来很有趣,但在实现这些特性方面并没有特别的帮助。关于如何使用if-modified-since、cachecontrol或etags的任何帮助或指针?

    3 回复  |  直到 6 年前
        1
  •  27
  •   sfussenegger    15 年前

    事实上,答案并不是针对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();
    }
    
        2
  •  5
  •   Jan Algermissen    12 年前

    在即将推出的JAX-RS2.0中,可以声明性地应用缓存控制,如中所述。 http://jalg.net/2012/09/declarative-cache-control-with-jax-rs-2-0/

    你至少可以用泽西来测试这个。但是,对cxf和resteasy不确定。

        3
  •  0
  •   loicmathieu    7 年前

    cxf没有实现动态过滤,如下所述: http://www.jalg.net/2012/09/declarative-cache-control-with-jax-rs-2-0

    如果您使用直接返回自己的对象而不是cxf响应,则很难添加缓存控制头。

    我找到了一种优雅的方法,使用自定义注释并创建一个cxf拦截器来读取这个注释并添加头。

    因此,首先,创建一个cachecontrol注释

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

    然后,将这个注释添加到您的cxf操作方法中(如果您使用一个接口,则它在这两个方法上都起作用的接口或实现)。

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

    然后创建一个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()));
        }
    }
    

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

    希望能有所帮助。

    罗氏C