Is it possible to set ETags using JAX-RS without resorting to Response objects?

前端 未结 3 490
心在旅途
心在旅途 2021-02-04 10:21

In one of the few questions (with answers) I have found on SO regarding JAX-RS and caching, the answer to generating ETags (for caching) is by setting some values on the Respons

相关标签:
3条回答
  • 2021-02-04 10:36

    You might consider using a Response Filter for that. I developed a smell library doing exactly what you are looking for: https://github.com/tobilarscheid/jaxrs-etag-filter

    0 讨论(0)
  • 2021-02-04 10:48

    or it can be as simple as sending back an "error" code... depending on what you want to do.

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

    That's how I tackled the issure anyway. Good luck! (Use Spring MVC instead.... there's an out of the box filter that does EVERYTHING for you... even making a good ETag :) )

    0 讨论(0)
  • 2021-02-04 10:49

    Yes you might be able to use interceptors to achieve this if you could generate the E-tag AFTER you create your response object.

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

    If that way isn't viable, I would use the original solution that you posted, and just add your Person entity to the builder:

    Person p = _dao.getPerson(name);
    return builder.entity(p).cacheControl(cc).lastModified(person.getUpdated()).build();
    
    0 讨论(0)
提交回复
热议问题