Java – Etag processing in spring MVC rest

I am considering switching from Apache CXF RS and Jax rs to spring MVC rest, and look at some problems in the way spring MVC rest is currently dealing with Etag Maybe I don't understand. Is there a better way to implement the work currently being done by Jax RS?

Use Apache CXF rs to evaluate the conditions of the last modified timestamp and Etag in the rest Service (the condition evaluation is actually quite complex, see RFC 2616 sections 14.24 and 14.26, so I'm happy to do it for me) The code looks like this:

@GET
@Path("...")
@Produces(MediaType.APPLICATION_JSON)
public Response findBy...(...,@Context Request request) {
       ... result = ...fetch-result-or-parts-of-it...;
       final EntityTag eTag = new EntityTag(computeETagValue(result),true);
       ResponseBuilder builder = request.evaluatePreconditions(lastModified,eTag);
       if (builder == null) {
              // a new response is required,because the ETag or time stamp do not match
              // ...potentially fetch full result object Now,then:
              builder = Response.ok(result);
       } else {
              // a new response is not needed,send "not modified" status without a body
       }
       final CacheControl cacheControl = new CacheControl();
       cacheControl.setPrivate(true); // store in private browser cache of user only
       cacheControl.setMaxAge(15); // may stay unchecked in private browser cache for 15s,afterwards revalidation is required
       cacheControl.setNoTransform(true); // proxies must not transform the response
       return builder
              .cacheControl(cacheControl)
              .lastModified(lastModified)
              .tag(eTag)
              .build();
}

I try the same thing as spring MVC rest. It looks like this:

@RequestMapping(value="...",produces=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<...> findByGpnPrefixCacheable(...) {
       ... result = ...fetch-result...;
//     ... result = ...fetch-result-or-parts-of-it...; - can't fetch parts,must obtain full result,see below
       final String eTag = "W/\""+computeETagValue(result)+"\""; // need to manually construct,as opposed to convenient JAX RS above
       return ResponseEntity
              .ok() // always say 'ok' (200)?
              .cacheControl(
                     CacheControl
                           .cachePrivate()
                           .maxAge(15,TimeUnit.SECONDS)
                           .noTransform()
                     )
              .eTag(eTag)
              .body(result); // ETag comparison takes place outside controller(?),but data for a full response has already been built - that is wasteful!
}

Even if not, I need to build all the data first to get a complete response This makes the Etag used in spring MVC rest far less valuable than it may be To my understanding, the idea of a weak Etag is to establish that its value may be "cheap" and compare it In happy situations, this prevents loading on the server When the resource is modified, of course, you need to build a complete response

In my opinion, by designing spring MVC rest, we need to build complete response data, regardless of whether the subject of the response is required in the end

Therefore, two questions about spring MVC rest are summarized:

>Is it equivalent to evaluateproconditions()? > Is there a better way to build Etag strings?

Thank you for your idea!

Solution

Yes, there is an equivalent method

You can use this:

@RequestMapping
public ResponseEntity<...> findByGpnPrefixCacheable(WebRequest request) {

    // 1. application-specific calculations with full/partial data
    long lastModified = ...; 
    String etag = ...;

    if (request.checkNotModified(lastModified,etag)) {
        // 2. shortcut exit - no further processing necessary
        //  it will also convert the response to an 304 Not Modified
        //  with an empty body
        return null;
    }

    // 3. or otherwise further request processing,actually preparing content
    return ...;
}

Please note that there are different versions of checknotmodified method, LastModified, Etag or both

You can find the document here: support for Etag and last modified response headers

Yes, but you have to change something first

You can change the way Etag is calculated so that you do not need to get complete results

For example, if the extraction result is a database query, you can add a version field to the entity and annotate it with @ version so that the field will be added each time you modify it, and then use the value for Etag

What's this for? Because you can configure fetching to be lazy, you don't need to retrieve all the fields of the entity, and you can also avoid hashing them to build etags Just use this version as the Etag string

This is a problem with using @ version in spring data project

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>