在one of the few questions (with answers)我发现有关JAX-RS和缓存的SO,生成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);
}
有没有办法 - 通过一些额外的配置 - 设置这些标题?这是我第一次发现使用Response对象实际上只比自动转换有一些好处......
我们正在使用Apache CXF。
答案 0 :(得分:7)
是的,如果您可以在创建响应对象后生成E-tag,则可以使用拦截器来实现此目的。
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实体添加到构建器中:
Person p = _dao.getPerson(name);
return builder.entity(p).cacheControl(cc).lastModified(person.getUpdated()).build();
答案 1 :(得分:1)
或者它可以像发回&#34;错误一样简单&#34;代码...取决于你想做什么。
@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 :))
答案 2 :(得分:0)
您可以考虑使用响应过滤器。我开发了一个完全符合您要求的气味库:https://github.com/tobilarscheid/jaxrs-etag-filter