简体   繁体   English

在REST服务(JAX-RS)中保存和更新数据

[英]Keep and update data in REST service (JAX-RS)

I am writing a REST service with jersey (JAX-RS). 我正在使用jersey(JAX-RS)编写REST服务。 Essentially, it should do the following: 本质上,它应该执行以下操作:

There is a text file with a lot of key=value pairs. 有一个带有很多键=值对的文本文件。 The user of the REST service should be able to query for a key and receive the value. REST服务的用户应该能够查询密钥并接收值。

Now it takes much too long to load and split the whole text file for every query. 现在,对于每个查询而言,加载和拆分整个文本文件都花费太长时间。 Instead I would like to load the text file into a Hashmap and reload it in fixed intervals. 相反,我想将文本文件加载到Hashmap中,并以固定间隔重新加载它。

I do not know how to implement this behaviour so that the Hashmap survives between queries, and that querying the REST service while it reloads the data does not cause concurrency issues. 我不知道如何实现此行为,以使Hashmap在两次查询之间得以生存,并且在重新加载数据时查询REST服务不会导致并发问题。

What should I do to have such a "cache" in my application? 我应该怎么做才能在应用程序中拥有这样的“缓存”?

JAX-RS default resource lifecycle is per-request (Request scope), so you need to mark your resource as @Singleton instead, to make it shared across the concurrent requests. JAX-RS默认资源生命周期是每个请求的(请求范围),因此您需要将资源标记为@Singleton ,以使其在并发请求中共享。

@Singleton @辛格尔顿

javax.inject.Singleton javax.inject.Singleton

In this scope there is only one instance per jax-rs application. 在这个范围内,每个jax-rs应用程序只有一个实例。 Singleton resource can be either annotated with @Singleton and its class can be registered using the instance of Application. 可以使用@Singleton注释单例资源,并且可以使用Application实例注册其类。 You can also create singletons by registering singleton instances into Application. 您还可以通过将单例实例注册到Application中来创建单例。

Life-cycle of Root Resource Classes 根资源类的生命周期

Next you need to implement a periodically refreshed thread-safe cache, to store your map. 接下来,您需要实现一个定期刷新的线程安全缓存,以存储您的地图。

I will normally use Guava CacheBuilder to do this: 我通常会使用Guava CacheBuilder来做到这一点:

private final LoadingCache<Object,Map<String,String>> cache;
protected final Object CACHE_KEY = new Object();    

//Create a Cache and keep it in the instance variable
public MyClass() {
    this.cache = CacheBuilder.newBuilder()
        .maximumSize(1)
        .refreshAfterWrite(10,TimeUnit.MINUTES)
        .build(new CacheLoader<Object,Map<String,String>>() {
            @Override
            public Map<String, String> load(Object key) {
                //Parse your file and return a Map<String,String>
            }
        });
 }

 @GET
 public void doIt() {
      //Get a cached copy of your Map
      Map<String,String> values = cache.get(CACHE_KEY);
 }

The cache instance is safe to use across the multiple threads (though you still have to take care of the thread safety of the object you return from cache), and will automatically refresh your entry once in 10 minutes. 可以安全地在多个线程中使用缓存实例(尽管您仍然需要注意从缓存返回的对象的线程安全性),并且它将在10分钟内自动刷新一次条目。

In a more complex system you may also want to create your LoadingCache instance elsewhere, and just inject it into your resource class (in this case you could keep it the request scoped). 在更复杂的系统中,您可能还想在其他位置创建LoadingCache实例,然后将其注入资源类中(在这种情况下,您可以将其限制在请求范围内)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM