如何在静态列表中捕获请求数据

时间:2017-04-04 10:12:38

标签: java spring-mvc servlets web servlet-3.0

我有一个例如:

的网址
http://some_url.suffix?data=test1.

我将有多种请求:

http://some_url.suffix?data=test1
http://some_url.suffix?data=test2
http://some_url.suffix?data=test3
http://some_url.suffix?data=test4

我想在服务器端维护一个静态列表,该列表将包含从所有会话中的请求接收的数据

List<String> data;

列表将包含data1,data2,data3,data4。列表将在特定间隔后清除,新列表将用于后续请求。 实现这一目标的最佳选择是什么:

1. static List<String> data = new CopyOnWriteArrayList<String>();
2. Singleton wrapper class to perform operation on normal java.util.List
3. using synchronized block

2 个答案:

答案 0 :(得分:0)

我会使用带有方法

的Singleton服务
public boolean addKey(String key, String value);

然后在您的服务中我将使用HashMap&gt;

private static Map<String, List<String>> keysMap;

private Map<String, List<String>> getKeysMap(){
    synchronized (this){        
        if(keysMap == null){
            keysMap = new HashMap();
        }
        return keysMap; 
    }
}

public void addKey(String key, String value){
    List<String> keyParams = getKeysMap().get(key);
    if(keyParams == null){
        keyParams = new ArrayList();
    }  
    //decide here if you want to store repeated values
    keyParams.add(param);
    getKeysMap().put(key, keyParams);
}

答案 1 :(得分:0)

第一个解决方案可能会导致性能问题,因为阵列将在每个传入请求中复制。

第三种解决方案更好,只需记住内部锁也应该是控制器/服务上的静态对象。这也需要在每次触摸data时记住同步块,所以这可能不是最佳解决方案。

第二个选项是针对该案例的最佳解决方案。创建在内部存储data的单例,并提供synchronized方法来使用它。同步内容将在一个类中关闭。

我尝试实现该单例包装器看起来像:

//Use enum to have singleton provided by jvm
enum DataCache {

    INSTANCE;

    //Use LinkedList if you expecting many calls. The insertion will be much faster.
    private List<String> data = new LinkedList<>();

    synchronized void add(String value) {
        data.add(value);
    }

    /*
     * Returns defensive copy, so that no one has reference to this.data.
     * If data is fetched only on clear you can make this private instead of synchronized 
     * (or even better get rid of it and create defensive copy inside clear()).
     */
    synchronized List<String> get() {
        return new ArrayList<>(data); 
    }

    /*
     * Returns last snapshot of data to keep consistency.
     */
    synchronized List<String> clear() {
        List<String> lastSnapshot = get();
        data = new LinkedList<>();
        return lastSnapshot;
    }
}

然后,您可以在处理请求的方法中使用INSTANCE.add(),在调度程序中使用INSTANCE.clear()

注意我不知道您如何使用收集的数据,但请考虑其他收集而不是列表。如果特定数据出现的数量不重要,最好用ListSet实现替换HashSet。 (就像你两次收到data=test1时一样,你只关心test1无论多少次都来了。如果您关心数字,您还可以考虑将值映射到出现次数。