كيفية استخدام التخزين المؤقت CXF و JAX-RS و HTTP
-
21-09-2019 - |
سؤال
ال CXF يذكر الوثائق التخزين المؤقت HTTP المتقدمة:
يوفر CXF Jaxrs دعمًا لعدد من ميزات HTTP المتقدمة عن طريق التعامل مع رؤوس IF-Match و IF-Modive-Since و ETAGS. يمكن استخدام كائن سياق طلب jaxrs للتحقق من الشروط المسبقة. تختلف ، يتم دعم cachecontrol وملفات تعريف الارتباط والطبخ المحدد.
أنا مهتم حقًا باستخدام (أو على الأقل استكشاف) هذه الميزات. ومع ذلك ، في حين أن "يوفر الدعم" يبدو مثيرًا للاهتمام حقًا ، إلا أنه ليس من المفيد بشكل خاص تنفيذ هذه الميزات. أي مساعدة أو مؤشرات حول كيفية استخدام ما إذا كان المعدّد ، أو cachecontrol أو etags؟
المحلول
في الواقع ، الإجابة ليست خاصة بـ CXF - إنها Jax -RS النقية:
// 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();
}
نصائح أخرى
مع Jax-RS 2.0 القادم ، سيكون من الممكن تطبيق التحكم في ذاكرة التخزين المؤقت بشكل إعلاني ، كما هو موضح في http://jalg.net/2012/09/declarative-cache-control-with-jax-rs-2-0/
يمكنك بالفعل اختبار هذا على الأقل مع جيرسي. لست متأكدا من CXF والراحة رغم ذلك.
لم ينفذ 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
أتمنى أن يساعد ذلك.
لو