2012-07-03 24 views
12

one of the few questions (with answers)我已经找到关于JAX-RS和缓存的SO,生成ETags(用于缓存)的答案是通过在Response对象上设置一些值。如下面的:是否可以使用JAX-RS设置ETags而不使用Response对象?

@GET 
@Path("/person/{id}") 
public Response getPerson(@PathParam("id") String name, @Context 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(); 
} 

的问题是不会被注释与@WebMethod(SOAP),@ GET方法为我们工作,因为两者都会使用SOAP相同的方法和REST服务,(和我们可能需要披露该服务的其他任何内容)。以前的服务是这样给我们(不包括创建头):

@WebMethod 
@GET 
@Path("/person/{id}") 
public Person getPerson(@WebParam(name="id") @PathParam("id") String name){ 
    return _dao.getPerson(name); 
} 

有什么办法 - 通过一些额外的配置 - 设置这些头的?这是我第一次发现使用Response对象实际上比自动转换有一些好处...

我们正在使用Apache CXF。

+0

我可能使用某种拦截器吗? http://stackoverflow.com/questions/3165647/apache-cxf-how-to-add-custom-http-header-to-jax-rs-response?rq=1 – oligofren

回答

7

是的,如果您可以在创建响应对象后生成电子标签,那么您可能可以使用拦截器来实现此目的。

public class MyInterceptor extends AbstractPhaseInterceptor<Message> { 

    public MyInterceptor() { 
     super(Phase.MARSHAL); 
    } 

    public final void handleMessage(Message message) { 
     MultivaluedMap<String, Object> headers = (MetadataMap<String, Object>) message.get(Message.PROTOCOL_HEADERS); 

     if (headers == null) { 
      headers = new MetadataMap<String, Object>(); 
     }    

     //generate E-tag here 
     String etag = getEtag(); 
     // 
     String cc = 600; 

     headers.add("E-Tag", etag); 
     headers.add("Cache-Control", cc); 
     message.put(Message.PROTOCOL_HEADERS, headers); 
    } 
} 

如果这种方式是不可行的,我会用你张贴原来的解决方案,并且只需添加您的个人实体建设者:

Person p = _dao.getPerson(name); 
return builder.entity(p).cacheControl(cc).lastModified(person.getUpdated()).build(); 
1

,或者它可以像发送一样简单返回一个“错误”代码......取决于你想要做什么。

@Path("/{id}") 
@GET 
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) 
public ProductSearchResultBean getProductById(@PathParam("id") Integer productId, @QueryParam("expand") List<String> expand, @Context HttpServletRequest request, @Context HttpServletResponse response) throws IOException { 

    ProductSearchResultBean productDetail = loadProductDetail(productId, expand); 

    EntityTag etag = new EntityTag(((Integer)(productDetail.toString().hashCode())).toString()); 
    String otherEtag = request.getHeader("ETag"); 
    if(etag.getValue().equals(otherEtag)){ 
     response.sendError(304, "not Modified"); 
    } 

    response.addHeader("ETag", etag.getValue()); 

    return productDetail; 
} 

这就是我如何解决发行问题。祝你好运! (使用Spring MVC代替....有一个开箱即用的过滤器,可以为你做一切...甚至可以制作一个好的ETag :))

相关问题