是否有可能设置使用JAX-RS的ETag不诉诸响应对象?(Is it possible to set

2019-07-30 05:42发布

在的几个问题(附答案)一个我已经在SO关于JAX-RS和缓存中发现,答案产生的ETag(用于缓存)是由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();
}

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

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

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

我们使用Apache CXF。

Answer 1:

是的,你可能能够使用拦截器来实现这一点,如果在创建您的响应对象,您可以生成电子标签。

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


Answer 2:

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

@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;
}

这就是我如何解决的issure反正。 祝好运! (使用Spring MVC代替....有一个开箱过滤器,做一切对你的......甚至制定好ETag的:))



Answer 3:

你可能会考虑使用一个响应滤波器。 我公司开发的气味库究竟做你在找什么: https://github.com/tobilarscheid/jaxrs-etag-filter



文章来源: Is it possible to set ETags using JAX-RS without resorting to Response objects?