Jersey.I を使用して安らかな API を開発しようとしています。GET が同じクライアントから同じ時間を取っている特定の取得操作用の GET API があります。応答をキャッシュすることは可能ですか? 任意のポインタをいただければ幸いです。
ありがとう
CacheControl、eTag を使用できます。以下のサンプル コードに従ってください。
// In your jersey method
final EntityTag eTag = new EntityTag(resource.getId() + "_" +
resource.getLastModified().getTime());
final CacheControl cacheControl = new CacheControl();
cacheControl.setMaxAge(-1);
ResponseBuilder builder = request.evaluatePreconditions(
resource.getLastModified(), eTag);
// the resoruce's information was modified, return it
if (builder == null) {
builder = Response.ok(resource);
}
// the resource's information was not modified, return a 304
return builder.cacheControl(cacheControl).lastModified(
resource.getLastModified()).tag(eTag).build();
resource
Resource インスタンスに置き換えます。
ソリューションの概要:
メソッドパラメータとしてリクエスト
インターフェース:
@Path("myentity")
public interface MyEntityResource
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getMyEntity(@Context final Request request);
}
実装:
public class MyEntityResourceImpl implements MyEntityResource
@Override
public Response getMyEntity(final Request request) {
final MyEntity myEntity = ... // load entity
final String eTagValue = ... // calclutate value of ETag
final EntityTag eTag = new EntityTag(eTagValue);
ResponseBuilder responseBuilder = request.evaluatePreconditions(eTag);
if (responseBuilder == null) {
return Response.ok(user).tag(eTag).build();
}
return responseBuilder.build();
}
}
短所:
実装の詳細Request
が公開されています
戻り値の型Reponse
はジェネリックです
WADL の戻り型の文法がありません
不要なパラメータを持つクライアント プロキシRequest
インスタンス変数としてリクエスト
インターフェース:
@Path("myentity")
public interface MyEntityResource
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getMyEntity();
}
実装:
public class MyEntityResourceImpl implements MyEntityResource
@Context
private Request request
@Override
public Response getMyEntity() {
final MyEntity myEntity = ... // load entity
final String eTagValue = ... // calclutate value of ETag
final EntityTag eTag = new EntityTag(eTagValue);
ResponseBuilder responseBuilder = request.evaluatePreconditions(eTag);
if (responseBuilder == null) {
return Response.ok(user).tag(eTag).build();
}
return responseBuilder.build();
}
}
短所:
戻り値の型Reponse
はジェネリックです
WADL の戻り型の文法がありません
依存性注入@Context
は複雑です。 https://stackoverflow.com/questions/33240443を参照してください
Web フィルターとしてのShallowEtagHeaderFilter
web.xml:
<filter>
<filter-name>etagFilter</filter-name>
<filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>etagFilter</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
インターフェース:
@Path("myentity")
public interface MyEntityResource
@GET
@Produces(MediaType.APPLICATION_JSON)
public MyEntity getMyEntity();
}
実装:
public class MyEntityResourceImpl implements MyEntityResource
@Override
public MyEntity getMyEntity() {
final MyEntity myEntity = ... // load entity
return myEntity;
}
}
短所:
サーバーのパフォーマンスが悪い。JavaDocを参照
コミットされていない応答でのみ機能します
弱い ETagのサポートなし
JAX-RS インターセプターとしてのカスタムWriterInterceptor
インターセプター:
public class CustomInterceptor implements WriterInterceptor {
@Context
private Request request;
@Override
public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
OutputStream old = context.getOutputStream();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
try {
context.setOutputStream(buffer);
context.proceed();
byte[] entity = buffer.toByteArray();
String etag = ... // calclutate value of ETag
context.getHeaders().putSingle(HttpHeaders.ETAG, etag);
ResponseBuilder responseBuilder = request.evaluatePreconditions(eTag);
if (responseBuilder == null) {
throw new WebApplicationException(responseBuilder.status(Response.Status.NOT_MODIFIED).header(HttpHeaders.ETAG, etag).build());
}
old.write(entity);
} finally {
context.setOutputStream(old);
}
}
}
参照: ServerCacheInterceptor (Resteasy)
インターフェース:
@Path("myentity")
public interface MyEntityResource
@GET
@Produces(MediaType.APPLICATION_JSON)
public MyEntity getMyEntity();
}
実装:
public class MyEntityResourceImpl implements MyEntityResource
@Override
public MyEntity getMyEntity() {
final MyEntity myEntity = ... // load entity
return myEntity;
}
}
短所:
Jersey の事前定義されたインターセプターは利用できません
サーバーのパフォーマンスが悪い
弱い ETagのサポートなし
醜い回避策WebApplicationException
Ehcacheのように、Jersey と一緒に標準の Java に適用可能な任意のキャッシュ メカニズムを使用できます。
バックエンドのデータが変更されていないことを確認するだけに注意する必要があります。
を使用した簡単な例を次に示しEhcache
ます。
@GET
@Path("{id}")
public List<Data> getData(@PathParam("id") Long id) {
Element element = CacheManager.getInstance().getCache("test").get(id);
if(element == null) {
Data value = fetchElementFromBackend(id);
CacheManager.getInstance().getCache("test").put(new Element(id, value));
return value;
}
return element.getObjectValue();
}