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
很好的答案。我唯一的评论是你生成的EntityTag可能不需要该人的UUID。电子标签在相同资源的修订之间更改是非常重要的。假设ID是不可变的,UUID与资源的路径是多余的(尽管你的Impl调用该参数为“name”,所以也许它不是不可变的),并且你应该确保这个值是表示特定的。资源的两种表示方式因媒体类型而异,请使用媒体类型值和版本标识符来创建表示特定的ETag值。 – benvolioT 2011-08-04 20:01:36
我从不使用Response对象 - 只需让CXF处理该部分即可。没有它? – oligofren 2012-06-30 12:12:48
@oligofren我以前从未使用过它们,但那是我找到的唯一解决方案。 – sfussenegger 2012-07-02 15:06:12