我需要在servlet启动时从数据库“预加载”一些数据。
所以我想创建一些缓存,例如使用HashMap
或类似的同步版本。
我还需要更新数据库更新更改的缓存 所以我想添加一些“听众”。
我的问题是:这是以某种方式提供还是我必须实际实现它?
如果是,那么哪种设计模式是最佳方法?
更新
没有使用JPA或ORM。但春天可用
答案 0 :(得分:3)
是的,你当然可以实现这一点 我将绘制一个小型架构然后向你解释它:
首先,您可以了解Mappers here和TDG here。 映射器有一个名为 cacheAll()的方法,它调用并委托给TDG的方法 cacheAll(),该方法的任务是从数据库中获取表中的所有行(要在缓存对象中缓存的行)。
所以首先你要创建一个实现“ServletContextListener”的监听器 这意味着它是整个servlet上下文的监听器,并且在其 contextInitialized 中你必须调用 mp.fill(Mapper.cacheAll()),所以它就像(这是通用代码,当然写得更好并优化它)
public class myServletContextListener implements ServletContextListener{
@Override
public void contextInitialized(ServletContextEvent sce) {
mp.fill(Mapper.cacheAll());
}
//
}
不要忘记在web.xml中添加你的监听器:
<listener>
<listener-class>myServletContextListener </listener-class>
</listener>
所以这将做什么,是在服务器启动时,将所有记录缓存到缓存对象中的hashmap mp。
至于根据数据库更改更新缓存,您必须使用observer pattern。
更新的
我忘了提及,关于缓存对象,我假设您希望所有用户或您的应用都可以访问它,因此您应该将其编码为单例(单例模式),代码如下:
public class cacheObject
{
private static Map cMap;
private static cacheObject cObject;
private cacheObject()
{
cMap = Mapper.cacheAll();
}
public static synchronized cacheObject getInstance()
{
if (cObject == null){
cObject = new cacheObject();
}
return cObject;
}
}
此外,如果您要缓存的数据可以由用户更改,那么请将其设为 Threadlocal 单例。
答案 1 :(得分:2)
您可以在Guava点找到最符合您需求的服务。 Caches上的wiki article可能与您最相关,但这里的确切方法在很大程度上取决于数据库更新更改的条件。如果要刷新数据库更新更改的整个缓存 - 或者至少使旧条目无效 - 只要发生数据库更新,您就可以调用Cache.invalidateAll()
。如果您愿意让缓存略微落后于时间,那么使用CacheBuilder.refreshAfterWrite(long, TimeUnit)
可能会对您有效。
答案 2 :(得分:0)
Hashmap和它的线程安全变体ConcurrentHashMap已经可用。
有一些缓存解决方案可以像ehcache一样提供,它也提供了诸如驱逐策略等高级支持。
关于设计模式,请阅读Observer设计模式。
答案 3 :(得分:0)
我实际上有一个生产水平项目,我需要做这样的事情。我的解决方案是(这只是我的解决方案)是在servlet启动时将对象(你的“数据”)加载到内存中。做出这个决定是因为该对象足够大,使得客户端请求缓慢从数据库中提取并且我有少量并发用户。任何会在数据库中更改该对象数据的请求也会更改内存中的对象。如果您正在与许多用户合作,您当然需要使用同步对象来执行此操作。如果数据量不是很大,那么每次用户请求有关数据的信息时,您都可以随时从数据库中提取数据。
祝你好运。