使用CDI简化JAX-RS缓存

这篇文章(通过一个简单的示例)说明了如何使用CDI Producers使其在RESTful服务中利用缓存控制语义更加容易

与HTTP 1.0中可用的Expires标头相比, HTTP 1.1中添加了Cache-Control标头,这是急需的改进。 RESTful Web服务可以利用此标头来扩展其应用程序并使它们更有效,例如,如果您可以缓存先前请求的响应,那么显然,如果您确定对以下内容,则无需再次向服务器发出相同的请求您缓存的数据不是陈旧的事实!

JAX-RS有何帮助?

自其初始(1.0)版本以来, JAX-RS就已经支持Cache-Control标头。 CacheControl类表示现实世界中的Cache-Control HTTP标头,并提供了通过简单的setter方法配置标头的功能。 JAX-RS 2.0 javadocs中有关CacheControl类的更多信息

jaxrs缓存控制

那么我该如何使用

只需返回一个Response对象,即可围绕它包装 CacheControl类的实例。

@Path("/testcache")
public class RESTfulResource {
    @GET
    @Produces("text/plain")
    public Response find(){
        CacheControl cc = new CacheControl();
        cc.setMaxAge(20);
        return Response.ok(UUID.randomUUID().toString()).cacheControl(cc).build();
    }
}

尽管这对于单个方法来说相对方便,但是重复创建和返回CacheControl对象可能会激怒多个方法

CDI生产者来抢救!

CDI生产者可以帮助注入类的实例,这些类在技术上不是Bean (按照严格的定义),或者对于您无法控制的类,要使用范围和限定符进行修饰。

这个想法是为了

  • 有一个自定义注释( @CacheControlConfig )来定义Cache-Control标头的默认值,并在您要覆盖它时提供灵活性
    @Retention(RUNTIME)
    @Target({FIELD, PARAMETER})
    public @interface CachControlConfig {
        
        public boolean isPrivate() default true;
        public boolean noCache() default false;
        public boolean noStore() default false;
        public boolean noTransform() default true;
        public boolean mustRevalidate() default true;
        public boolean proxyRevalidate() default false;
        public int maxAge() default 0;
        public int sMaxAge() default 0;
    
    }
  • 只需使用CDI Producer通过使用InjectionPoint对象(由CDI高兴地注入!)来创建CacheControl类的实例,具体取决于注释参数
    public class CacheControlFactory {
    
        @Produces
        public CacheControl get(InjectionPoint ip) {
    
            CachControlConfig ccConfig = ip.getAnnotated().getAnnotation(CachControlConfig.class);
            CacheControl cc = null;
            if (ccConfig != null) {
                cc = new CacheControl();
                cc.setMaxAge(ccConfig.maxAge());
                cc.setMustRevalidate(ccConfig.mustRevalidate());
                cc.setNoCache(ccConfig.noCache());
                cc.setNoStore(ccConfig.noStore());
                cc.setNoTransform(ccConfig.noTransform());
                cc.setPrivate(ccConfig.isPrivate());
                cc.setProxyRevalidate(ccConfig.proxyRevalidate());
                cc.setSMaxAge(ccConfig.sMaxAge());
            }
    
            return cc;
        }
    }
  • 只需 CacheControl实例注入您的REST资源类中,并在您的方法中使用它
    @Path("/testcache")
    public class RESTfulResource {
        @Inject
        @CachControlConfig(maxAge = 20)
        CacheControl cc;
    
        @GET
        @Produces("text/plain")
        public Response find() {
            return Response.ok(UUID.randomUUID().toString()).cacheControl(cc).build();
        }
    }

其他想法

  • 在这种情况下,产生的CacheControl实例的作用域为@Dependent,即它将与注入它的类一起生存和死亡。 在这种情况下,由于JAX-RS容器为每个客户端请求创建了一个新实例,因此JAX-RS资源本身是RequestScoped (默认),因此将与每个HTTP请求一起创建注入的CacheControl实例的新实例。
  • 您还可以引入CDI限定词以进一步缩小范围并考虑极端情况
  • 您可能会认为,使用JAX-RS过滤器可以实现相同的目的。 那是正确的。 但是您需要手动设置Cache-Control标头(在可变的MultivaluedMap中),并且逻辑不够灵活,无法解决不同情况下的不同Cache-Control配置

实验结果

使用NetBeans IDE播放此示例(推荐)

尽管代码很简单,但是如果您觉得很懒,可以从这里获取(maven)项目并在其中玩转

玩得开心!

翻译自: https://www.javacodegeeks.com/2015/02/simplifying-jax-rs-caching-with-cdi.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值