问题描述
这是由之前的一个问题《Java中多层级一对多关系的处理》引发的,当时我为了让用户的http请求,可以复用数据库的数据,将一个包含数据的service作用域设置为了request。
后面这个service在后台跑的job中也用到了,此时会报错:
Scope ‘request’ is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton
想了几个方案,都有问题:
1、将这个bean类的作用域设置为多例@Scope(“prototype”)
经测试,发现因为这个类只会在Spring容器初始化的时候加载一次,因此每个用户过来调用的实例,都是同一个,这样后台数据更新后,用户这边就无法及时获取到变更内容。
2、不缓存数据,每次都查询数据库
该类提供了一个类似getXXXById(int id)的方法,这个方法被调用的频率非常高,如果每次都查询数据库,吃不消。
后来想到,要不给这个数据设置一个缓存时间吧,通过Spring容器默认单例的特性,这样既能复用数据,又能保证数据更新不会太延迟。经过测试,这个方案是可行的。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| abstract public class MySQLCacheServiceImpl implements CacheService {
protected HashMap<Integer, Object> data = null;
protected long initTime = 0;
protected void reload() { long ts = System.currentTimeMillis(); if (0 == initTime || ts - initTime >= 60000 || null == data) { try { data = initCache(); } catch (Exception exp) { exp.printStackTrace(); } initTime = ts; } }
@Override public ArrayList addAttributesForIds(List<Integer> ids) { this.reload();
ArrayList dataList = new ArrayList(); for (int id : ids) { if (null != data.get(id)) { dataList.add(data.get(id)); } } return dataList; }
abstract protected HashMap<Integer, Object> initCache();
}
|