21

RESTful Web サービスを作成しているときに、クライアント (現在は .NET シック クライアント) で何らかの種類のキャッシュを有効にすると問題が発生します。デフォルトでは、Jersey はいかなる種類のキャッシュ制御ヘッダーも送信しないため、クライアントはほとんどのページを自動的にキャッシュします (これは有効な動作のようです)。

デフォルトでJerseyに「キャッシュなし」のキャッシュコントロールを送信させ、特定の応答でキャッシュコントロールをオーバーライドしたいと思います。

ジャージーでこれを行う方法はありますか?

RESTeasy には @NoCache アノテーションを使用してクラス全体の設定を指定する機能があることがわかりましたが、Jersey と同様のものは見つかりませんでした。

4

5 に答える 5

24

これは、Jersey では ResourceFilterFactory を使用して簡単に行うことができます。メソッドにアタッチするカスタム アノテーションを作成して、キャッシュ コントロール設定を設定できます。ResourceFilterFactories は、アプリケーションの初期化時に、検出された各リソース メソッドに対して呼び出されます - ResourceFilterFactory で、メソッドに @CacheControlHeader アノテーション (または呼び出したいもの) があるかどうかを確認できます - そうでない場合は、「no-cache」を追加する応答フィルターを返すだけです" ディレクティブを応答に追加する必要があります。それ以外の場合は、注釈の設定を使用する必要があります。これを行う方法の例を次に示します。

public class CacheFilterFactory implements ResourceFilterFactory {
    private static final List<ResourceFilter> NO_CACHE_FILTER = Collections.<ResourceFilter>singletonList(new CacheResponseFilter("no-cache"));

    @Override
    public List<ResourceFilter> create(AbstractMethod am) {
        CacheControlHeader cch = am.getAnnotation(CacheControlHeader.class);
        if (cch == null) {
            return NO_CACHE_FILTER;
        } else {
            return Collections.<ResourceFilter>singletonList(new CacheResponseFilter(cch.value()));
        }
    }

    private static class CacheResponseFilter implements ResourceFilter, ContainerResponseFilter {
        private final String headerValue;

        CacheResponseFilter(String headerValue) {
            this.headerValue = headerValue;
        }

        @Override
        public ContainerRequestFilter getRequestFilter() {
            return null;
        }

        @Override
        public ContainerResponseFilter getResponseFilter() {
            return this;
        }

        @Override
        public ContainerResponse filter(ContainerRequest request, ContainerResponse response) {
            // attache Cache Control header to each response based on the annotation value
            response.getHttpHeaders().putSingle(HttpHeaders.CACHE_CONTROL, headerValue);
            return response;
        }
    }
}

注釈は次のようになります。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CacheControlHeader {
    String value();
}

ResourceFilterFactory は、次の init パラメータを web.xml の Jersey サーブレットの定義に追加することで、アプリケーションに登録できます。

<init-param>
    <param-name>com.sun.jersey.spi.container.ResourceFilters</param-name>
    <param-value>package.name.CacheFilterFactory</param-value>
</init-param>
于 2012-06-10T17:35:17.760 に答える
14

@martin-matula のソリューションに基づいて、2 つの Cache アノテーションを作成しました。1 つ@NoCacheはまったくキャッシュしない場合で、もう 1 つ@CacheMaxAgeは特定のキャッシュを使用する場合です。は 2 つのCacheMaxAge引数を取るため、自分で秒数を計算する必要はありません。

@GET
@CacheMaxAge(time = 10, unit = TimeUnit.MINUTES)
@Path("/awesome")
public String returnSomethingAwesome() {
    ...
}

ResourceFilter には、デフォルトで干渉しない次の create メソッドが含まれるようになりました (そのため、他のキャッシュ メカニズムは引き続き機能します)。

@Override
public List<ResourceFilter> create(AbstractMethod am) {
    if (am.isAnnotationPresent(CacheMaxAge.class)) {
        CacheMaxAge maxAge = am.getAnnotation(CacheMaxAge.class);
        return newCacheFilter("max-age: " + maxAge.unit().toSeconds(maxAge.time()));
    } else if (am.isAnnotationPresent(NoCache.class)) {
        return newCacheFilter("no-cache");
    } else {
        return Collections.emptyList();
    }
}

private List<ResourceFilter> newCacheFilter(String content) {
    return Collections
            .<ResourceFilter> singletonList(new CacheResponseFilter(content));
}

私のブログ投稿で完全なソリューションを見ることができます。

解決策をありがとうマーティン!

于 2013-07-28T11:37:55.897 に答える
2

私はあなたが使用できると思います

isNoCache(true)

これにより、ブラウザでのキャッシュが停止します。

見る:

http://jersey.java.net/nonav/apidocs/1.12/jersey/javax/ws/rs/core/CacheControl.html#isNoCache%28%29

お役に立てれば。

于 2012-06-07T15:31:53.883 に答える