2015-10-21 7 views
11

मैं वसंत MVC आराम JAX रुपये के साथ अपाचे CXF रुपये से स्विच से स्विच तलाश में हूं और जिस तरह से वसंत MVC बाकी वर्तमान में ETags से निपटने के साथ कुछ समस्याओं को देखते हैं। हो सकता है कि मैं सही समझ नहीं पा रहा हूं या वर्तमान में जेएक्स आरएस के साथ क्या किया जा रहा है, हासिल करने का एक बेहतर तरीका है?ETag हैंडलिंग

अपाचे सीएक्सएफ आरएस का उपयोग करते हुए, अंतिम संशोधित समय टिकट और ईटाग की शर्तों को आरईएसटी सेवा के अंदर मूल्यांकन किया जाता है (हालत मूल्यांकन वास्तव में काफी जटिल है, आरएफसी 2616 अनुभाग 14.24 और 14.26 देखें, इसलिए मुझे खुशी है कि यह किया जाता है मुझे)। कोड इस तरह दिखता है:

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

मैं पहले से पूरा जवाब के लिए सभी डेटा का निर्माण करने के लिए होने के साथ इस मुद्दे ले:

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

वसंत MVC बाकी के साथ एक ही बात पर मेरा प्रयास इस तरह दिखता है , भले ही आवश्यक नहीं है। यह ईटीएजी को स्प्रिंग एमवीसी आरईएसटी में इस्तेमाल किया जा सकता है जितना कम मूल्यवान हो सकता है। मेरी समझ के लिए एक कमजोर ईटाग का विचार यह है कि यह अपना मूल्य बनाने और इसकी तुलना करने के लिए "सस्ता" हो सकता है। खुश मामले में यह सर्वर पर लोड रोकता है। मामले में संसाधन को संशोधित किया गया था, बिल्कुल पूर्ण प्रतिक्रिया का निर्माण किया जाना चाहिए।

यह मेरे लिए प्रतीत होता है कि द्वारा डिजाइन वसंत MVC बाकी वर्तमान में निर्मित होने की पूर्ण प्रतिक्रिया डेटा, कोई फर्क नहीं पड़ता अगर प्रतिक्रिया के लिए एक शरीर अंततः की जरूरत है या नहीं की आवश्यकता है।

तो, सारांश में वसंत MVC बाकी दो प्रश्न:

  1. वहाँ evaluatePreconditions को एक बराबर() है?
  2. वहाँ ETag तार के निर्माण की एक बेहतर बेहतर तरीका है?

अपने विचारों के लिए धन्यवाद!

+0

अच्छा सवाल। मुझे लगता है कि यदि वसंत बॉक्स से बाहर नहीं प्रदान करता है, तो आप पूरे शरीर को बनाने के लिए कॉलबैक निष्पादित करने के लिए 'ResponseEntity' बढ़ा सकते हैं। – Augusto

+0

ऐसा लगता है कि आपको किसी भी मामले में 'परिणाम' को प्रीलोड करना होगा ... लेकिन मुझे लगता है कि, पहले मामले में, आपको केवल ईटाग की गणना करने के लिए कुछ सस्ता (उदा। संस्करण संख्या) चाहिए। मुझे लगता है कि सबसे अच्छा जवाब आलसी शरीर की इमारत करना है। – ZhongYu

+0

आखिरकार, कुछ अनुप्रयोगों में, सर्वोत्तम प्रदर्शन के लिए, एप्लिकेशन को स्वयं शर्तों का परीक्षण करना होगा। यह * वह * कठिन नहीं है। [यह] (https://github.com/zhong-j-yu/bayou/blob/0.9/src/bayou/http/ImplRespMod.java#L516) नवीनतम HTTP spec के विचार-विमर्श के आधार पर तर्क का मेरा कार्यान्वयन है । – ZhongYu

उत्तर

7
  1. हाँ, समकक्ष विधि है।

आप इस तरह इसका इस्तेमाल कर सकते हैं:

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

नोट checkNotModified विधि के विभिन्न संस्करणों, lastModified, ETag, या दोनों के साथ देखते हैं कि।

आप प्रलेखन यहाँ पा सकते हैं: Support for ETag and Last-Modified response headers


  1. हाँ, लेकिन आप पहली बार कुछ चीजें बदलना होगा।

आप ईटाग की गणना करने के तरीके को बदल सकते हैं ताकि आपको पूर्ण परिणाम प्राप्त करने की आवश्यकता न हो।

उदाहरण के लिए, यदि यह fetch-result डेटाबेस क्वेरी है, तो आप अपनी इकाई में एक संस्करण फ़ील्ड जोड़ सकते हैं और इसे @Version के साथ एनोटेट कर सकते हैं ताकि प्रत्येक बार संशोधित होने पर इसे बढ़ाया जा सके और फिर ETAT के लिए उस मान का उपयोग करें ।

यह क्या हासिल होता है?चूंकि आप आलसी होने के लिए लाने को कॉन्फ़िगर कर सकते हैं, आपको अपनी संस्थाओं के सभी क्षेत्रों को पुनर्प्राप्त करने की आवश्यकता नहीं है, और आप इसे ईटाग बनाने के लिए भी हैश करने से बचें। बस इटाग स्ट्रिंग के रूप में संस्करण का उपयोग करें।

यहां Using @Version in Spring Data project पर एक प्रश्न है।

संबंधित मुद्दे