2010-01-18 13 views
17

CXF प्रलेखन का उल्लेख है कैशिंग के रूप में Advanced HTTP:CXF, JAXRS और HTTP कैशिंग का उपयोग कैसे करें

CXF JAXRS समर्थन उन्नत HTTP में अनेक सुविधाओं के लिए से निपटने के हैं-मैच, यदि संशोधित बाद से प्रदान करता है और ईटैग हेडर। JAXRS अनुरोध संदर्भ ऑब्जेक्ट का उपयोग पूर्व शर्त जांचने के लिए किया जा सकता है। वेरी, कैश कंट्रोल, कुकीज़ और सेट-कुकीज़ भी समर्थित हैं।

मुझे इन सुविधाओं का उपयोग करने में वास्तव में रुचि है (या कम से कम अन्वेषण)। हालांकि, जबकि "समर्थन प्रदान करता है" वास्तव में दिलचस्प लगता है, यह ऐसी सुविधाओं को लागू करने में विशेष रूप से सहायक नहीं है। कोई मदद या पर संकेत कैसे यदि संशोधित के बाद से, CacheControl या ETags उपयोग करने के लिए?

उत्तर

27

वास्तव में, इस सवाल का जवाब CXF के लिए विशिष्ट नहीं है - यह शुद्ध JAX-रुपये है:

// IPersonService.java 
import javax.ws.rs.GET; 
import javax.ws.rs.Path; 
import javax.ws.rs.PathParam; 
import javax.ws.rs.core.Context; 
import javax.ws.rs.core.Request; 
import javax.ws.rs.core.Response; 

@GET 
@Path("/person/{id}") 
Response getPerson(@PathParam("id") String id, @Context Request request); 


// PersonServiceImpl.java 
import javax.ws.rs.core.CacheControl; 
import javax.ws.rs.core.EntityTag; 
import javax.ws.rs.core.Request; 
import javax.ws.rs.core.Response; 
import javax.ws.rs.core.Response.ResponseBuilder; 

public Response getPerson(String name, 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(); 
} 
+4

ग्रेट उत्तर। मेरी केवल टिप्पणी कि EntityTag आप शायद उत्पन्न व्यक्ति की UUID की जरूरत नहीं है है। यह केवल इतना महत्वपूर्ण है कि एक ही संसाधन के संशोधन के बीच एक ईटीएजी परिवर्तन। मान लीजिए कि अपरिवर्तनीय है, यूयूआईडी संसाधन के पथ के साथ अनावश्यक है (हालांकि आपका आईएमएल उस पैरामीटर "नाम" को कॉल करता है, इसलिए शायद यह अपरिवर्तनीय नहीं है। साथ ही, आपको यह सुनिश्चित करना चाहिए कि यह मान प्रतिनिधित्व-विशिष्ट है। उदाहरण के लिए, यदि एक संसाधन के दो अभ्यावेदन, मीडिया प्रकार के अनुसार भिन्न संस्करण पहचानकर्ता के साथ-साथ मीडिया प्रकार मान का उपयोग एक प्रतिनिधित्व विशेष ETag मूल्य बनाने के लिए – benvolioT

+0

मैं कभी नहीं एक रिस्पांस वस्तु का उपयोग करें -।। बस CXF वह हिस्सा संभालने दें आप कैसे करते हैं इसके बिना? – oligofren

+0

@oligofren मैंने कभी उन्हें पहले कभी नहीं इस्तेमाल किया था, लेकिन यह मुझे मिला एकमात्र समाधान था। – sfussenegger

5

आगामी JAX-RS 2.0 के साथ यह एलान के तौर पर कैश-नियंत्रण लागू करने के लिए संभव हो जाएगा, के रूप में http://jalg.net/2012/09/declarative-cache-control-with-jax-rs-2-0/ में विस्तार से बताया

आप पहले से ही कम से कम जर्सी के साथ इस परीक्षण कर सकते हैं। हालांकि सीएक्सएफ और रीस्टेसी के बारे में निश्चित नहीं है।

+0

यह घोषणात्मक रूप से अधिक है ऐसे फ़िल्टर लागू करना जो कैशिंग के रूप में ऐसी चीजें कर सकते हैं, लेकिन फिर भी एक बड़ा सुधार। मुझे (हमें) देने के लिए धन्यवाद। – sfussenegger

0

CXF गतिशील छानने लागू करता नहीं था, क्योंकि यहां विस्तार से बताया: http://www.jalg.net/2012/09/declarative-cache-control-with-jax-rs-2-0

और अगर आप सीधे अपने वस्तुओं और नहीं CXF रिस्पांस वापस जाने के लिए उपयोग करते हैं, यह एक कैश नियंत्रण हेडर जोड़ने के लिए मुश्किल है।

मैं एक कस्टम एनोटेशन का उपयोग करने और बनाने एक CXF इंटरसेप्टर कि यह व्याख्या पढ़ सकते हैं और शीर्ष लेख से एक सुंदर रास्ता खोजने।

तो सबसे पहले, फिर एक CacheControl एनोटेशन

@Target(ElementType.METHOD) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface CacheControl { 
    String value() default "no-cache"; 
} 

बनाने अपने CXF आपरेशन विधि को यह टिप्पणी जोड़ने (इंटरफ़ेस या कार्यान्वयन उस पर काम करता है दोनों तुम एक इंटरफ़ेस का उपयोग करता है, तो) फिर

@CacheControl("max-age=600") 
public Person getPerson(String name) { 
    return personService.getPerson(name); 
} 

एक CacheControl इंटरसेप्टर कि एनोटेशन संभाल और आपके उत्तर की शीर्ष लेख जोड़ देगा पैदा करते हैं।

public class CacheInterceptor extends AbstractOutDatabindingInterceptor{ 
    public CacheInterceptor() { 
     super(Phase.MARSHAL); 
    } 

    @Override 
    public void handleMessage(Message outMessage) throws Fault { 
     //search for a CacheControl annotation on the operation 
     OperationResourceInfo resourceInfo = outMessage.getExchange().get(OperationResourceInfo.class); 
     CacheControl cacheControl = null; 
     for (Annotation annot : resourceInfo.getOutAnnotations()) { 
      if(annot instanceof CacheControl) { 
       cacheControl = (CacheControl) annot; 
       break; 
      } 
     } 

     //fast path for no cache control 
     if(cacheControl == null) { 
      return; 
     } 

     //search for existing headers or create new ones 
     Map<String, List<String>> headers = (Map<String, List<String>>) outMessage.get(Message.PROTOCOL_HEADERS); 
     if (headers == null) { 
      headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); 
      outMessage.put(Message.PROTOCOL_HEADERS, headers); 
     } 

     //add Cache-Control header 
     headers.put("Cache-Control", Collections.singletonList(cacheControl.value())); 
    } 
} 

अंत में कॉन्फ़िगर CXF अपने इंटरसेप्टर उपयोग करने के लिए, आप सभी आवश्यक जानकारी यहाँ पा सकते हैं: http://cxf.apache.org/docs/interceptors.html

आशा है कि यह मदद मिलेगी।

Loïc

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